I have a json object with a function:
var thread = {
title: "my title",
delete: function() {
alert("deleted");
}
};
thread.delete(); // alerted "deleted"
thread_json = JSON.encode(thread); // convert to json from object
thread_object = JSON.decode(thread_json); // convert to object from json
thread_object.delete(); // this didn't work
After I converted it back from json string to object, I could not use delete() function.
When you convert something to json, the functions are gone?
Are there ways to keep them in the json string?
I'm using Mootools.
You got it. Take a look at that JSON.encode output. Only simple data types are allowed in JSON representations, partly for ease of creation, and partly for security. (The reason we use something like JSON.decode instead of eval is the possibility of embedding functions.)
You'll have to modify the JSON library source code to accept functions, or write your own in order to preserve the literal definition of the object upon conversion to string.
Consider, though, the possibility that you don't really need to do this. There's probably a better solution, but I can't begin to address that without knowing your exact situation.
Related
From the MDN documentation:
reviver (Optional)
If a function, prescribes how the value originally produced by parsing is transformed, before being returned.
Its name strikes me as odd. Maybe I’m missing a metaphor here — why would this be called “reviving” an object? Is there any history to such a transformer function being called a “reviver”? Googling reviver +javascript shows that JSON.parse is basically the only place where this term is used.
The idea is that native Javascript objects, like a Number(42), are your "live" objects. When you serialise those into a JSON representation, they're "dried up", or "dumbed down", or whatever you want to call it. To get your fresh live Javascript objects back, you need to "revive" them from their simple text representation.
This becomes more apparent if you use more complex objects:
function Foo(bar) {
this.bar = bar;
}
Foo.prototype.baz = function () {
alert(this.bar);
};
var f = Foo(42);
f.baz();
f = JSON.parse(JSON.stringify(f));
f.baz(); // Nope
To get the original object back which has a baz method, you need to do a little more than just parse it. That's the "reviving" part.
The parse function is used to create an object from data that has been serialized into a string. By default, all it can do is reconstitute the data into plain objects with a bunch of properties.
Sometimes, you may want to "bring these values back to life" (i.e. revive them) into full-fledged objects with methods, behaviors, etc., or even objects that have a particular type, instead of just the lifeless containers of values that JSON.parse() produces by default.
I would say that's why it's called a reviver.
I want to be able to parse external variables into a JSON object.
Something like this would do:
var username = "zvincze";
And using that variable to parse a JSON object:
var json = '{"username":"VARIABLE_GOES_HERE"}'
var obj = JSON.parse(json);
This is a very simple question that I can't seem to figure out. In fact, I don't even know if there's a way to actually acheive something such as this.
You need to distinguish carefully between JSON and JavaScript objects. They are two entirely different things.
JSON is a language-independent character-based data representation that is used for data interchange. For instance, if you are sending data to a server, it needs to be in string form, so you would need to convert your data into JSON. If you are receiving data from a server, and it is JSON format, you need to convert it into a JavaScript object so you can use it in your JavaScript program.
JSON actually has nothing to do with JavaScript. For example, JSON could be used as a string-based data representation for Java programs exchanging data. Java and pretty much all other languages provide their own library routines for converting their native data into JSON and vice versa.
The only relationship between JSON and JavaScript objects used in JavaScript is that a JSON string looks much like a JavaScript object literal, with some additional restrictions, such as that keys must be quoted, that it cannot hold certain data types such as functions, and that it cannot hold circular references.
The "JS" part of "JSON" does not indicate that JSON is a basic JavaScript data structure, or that JSON is used in JavaScript for representing or manipulating data. It merely comes from the fact that, as mentioned above, the format of a JSON string is loosely modeled after that of a JavaScript object literal.
In normal day-to-day JavaScript programming, you will never use JSON, and don't need to worry about it. You will need to worry about JSON only when, as I said, you are sending data to somewhere, or receiving data from somewhere, that expects JSON as the data format. That is the case when making ajax calls, of course, but actually, even then, since jQuery's $.ajax will automatically convert data to and from JavaScript objects if you tell it the right types, even in that case you do not normally need to worry about JSON.
Note by the way that JSON can represent primitive values, not just JavaScript objects. For example, "1" is valid JSON which represents the number 1.
As I understand your question, you want to create a JavaScript object (not JSON) which contains as one of its values that of the variable username. You create a JavaScript object with regular old JavaScript object literal format, in this case
{username: username}
This means, create an object, with a single key named "username" (quote it if you please), whose value is that of the variable username. Again, unless you plan to send this object somewhere that expects a JSON string representation, there is no need to even think about JSON in this case.
In theory, yes, as one answer suggested, you could create a JSON string with the value of username "interpolated", using string arithmetic like '{"username":"' + VARIABLE_GOES_HERE + '"}', and then convert that JSON string into a JavaScript object using JSON.parse. However, there is absolutely no reason to jump through these hoops, when you can simply write the JavaScript object as a normal JavaScript object literal.
Another answer shows a way to define a regular JavaScript object, and then turn it into JSON using JSON.stringify. However, again, in your case, there is no need to do this unless you are planning to send the object somewhere.
Yet another answer shows a way to define a regular JavaScript object, then stringify it into a JSON string, then immediately parse it back into a JavaScript object, which will be exactly the same object you started with before stringifying and parsing. There's absolutely no need to do this.
One sees no small number of questions on SO trying to somehow manipulate or search or replace within JSON, using regexps for example. There are almost no cases where you need to even think of doing such a thing. JSON has two fundamental operations: converting values into JSON, and converting JSON into values. Both of those are built into the language in the form of JSON.stringify and JSON.parse, that do their jobs with absolute reliability and performance. If for some reason you need to modify data which is in JSON string format, don't manipulate the string; all you need to do is parse it into a JavaScript value, manipulate the value, and then convert it back into JSON.
Unfortunately, for unknown reasons, many JavaScript programmers who are learning the language, including many who have posted questions here on SO, have developed the misperception that JSON is a JavaScript object, or that they must think about JSON and stringifying and parsing in order to deal with plain old JavaScript objects, which is very much not the case.
Minor point, but you use the term "parse" in your question. I see more and more people using this word for some reason to mean "access" or "retrieve" or "extract". Actually, "parse" has a very specific meaning: to analyze a string-based representation of information (such as a program or data object), according to a particular grammar, into some suitable computer-friendly form for further processing. What JSON.parse does is parsing in this sense, because it is analyzing a string-based representation of information according to the JSON grammar into a JavaScript object for further processing.
You can simply concatenate strings like below...
var json = '{"username":"' + VARIABLE_GOES_HERE + '"}'
in your case:
var username = "zvincze";
var json = '{"username":"' + username + '"}';
Happy coding....
I think what you're doing is sort of odd. The object you create is json by definition (JavaScript Object Notation).
var obj = {};
obj.username = "zvincze";
//obj is now json
var str = JSON.stringify(obj);
//str == {'username':'zvincze'}
JSON.parse(obj) should fail since obj is already json.
Without messing with concatenation var json = '{"username":"'+ userName +'"}' you can:
var ob = {}; // or simply: var ob = {username:"zvincze"};
ob.surname = "Zvincze";
ob.name = "Zachary";
ob.id = "5182842";
var json = JSON.stringify(ob);
var obj = JSON.parse(json);
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
var json = JSON.stringify({username:"zvincze"})
I have a website that returns a JSON-like data structure like this:
{
"name":"tom jones",
"no": 123,
"storedproc": function(){
callbuyer(0123);
}
}
I'm getting this data using $.ajax() with dataType "JSON". Unfortunately, my $.ajax() calls the error callback because my data contains a function().
How can I parse this correctly? I really need to store the function in a variable and call it later.
That is simply not legal JSON (as you know given the title of the question) See the offical JSON syntax. The nice thing about real JSON is that one can use JSON.parse which safely wraps an eval call.
While eval could be used, I would suggest revisiting the architecture of your application and find some other way to do what you are trying to do.
In particular, I would have the server return the 0123 only, and let your client keep the logic that lets it know, in certain cases, which functions apply (in the scenario here, the function would be callbuyer).
This should work because you say you want to call the function which is the value of the storedproc later. Since the body of this function contains a call to callbuyer it follows that your client side script knows what callbuyer is. The trick is for your server not to send back arbitrary, unconstrained functions, but rather data that your client can exploit somehow using the knowledge it has about the overall application.
Could you arrange to have the server return JSON like this:
{"name":"tom jones",
"no": 123,
"storeprocFn": callbuyer,
"arg": "0123"};
Then your callback function can call the callbuyer function and pass arg
Use eval to interpret the string as a javascript object. You won't be able to use the JSON data type though. I believe what you need to do is use 'text' as the dataType for the $.ajax call. Then do something like:
var data = eval('(' + text + ')');
Should work. Of course, eval is evil. But it would solve your problem. As long as you can guarantee there isn't anything malicious in the text (no unsanitized, user entered data) then you should be ok.
AFAIK, functions are left out when using JSON.stringify, it's just not meant to be used to clone full objects (props and methods). However, you might be able to pass the function body as a string.Say you decide on a string format like func=>var foo = 'bar'; return foo;. This should be passed as a regular JSON string, after parsing the object you could then iterate all properties, and convert those strings to functions like so:
for (var prop in parsedObj)
{
if (parsedObj.hasOwnProperty(prop) && parsedObj[prop].match(/^func\=\>/))
{
parsedObj[prop] = new Function(parsedObj[prop].replace('func=>',''));
}
}
Though, seriously, I'd say you might want to rethink your approach, this is not what JSON is for. It's unsafe, all JSON strings are eval'ed, after having made sure they contain no harmful code. This approach is creating a loophole/vulnerability that the JSON people worked hard for to seal off.
For your example will this work:
'user.storeproc = function() { callbuyer( user.no);};'
The Var 'user' is the object of the parsed json.
Ps: maybe you have to format user.no, from 123 to 0123
Following JSON extension, "JFON", does transport of functions and array-properties.
JFON uses eval and is intended for case if:
1) your data is from trusted source ( like not-derived from user input or is a code from your own server), and
2) you know there are no undesired side effects with context of "eval"
(it is a context of eval in function "fromJFON", line 127 )
3) it is costly to refactor your app to use "functionless" JSON;
4) JFON is one-day work, so may be needs more testing;
The idea: use selected property name to escape functions and arrays like
in strings when selected character "\" is used to pass \n and \ for itself.
In JFON, name "wrap" is selected to pass functions and itself: "wrap" : { "fun" : ... and "wrap" : { "esc" : ...
demo: http://landkey.org/Sandbox/z/spaceen86/js/btb/tests/jfon.htm
code ( use commit 0.0.86 ):
https://github.com/lancelab/spaceen/blob/master/js/btb/JFON.js
test: github.com/lancelab/spaceen/blob/master/js/btb/tests/jfon.htm
Here is another, "JWON" extension: JSON-comments, here-documents, monkey-patching of JSONs:
github.com/lancelab/Boardspirator/blob/master/diary/play/tp/jwon.js
I have an object that contains arrays which is made up of other arrays it also contains methods. The problem that i am facing is that i can't use JSon because of the multidimensional arrays and the methods.
The reason i want to convert it to a string is to store into the Iphone's
localStorage.
you can only store text inside of there and i was hoping for a way to store a complex object about a user as a string and able to deserialize it again after. Is there even a way to do this. I don't know javascript well enough to write my own api. That was the option i started to try and look into at this point :(
Serialize it to JSON. You can serialize / deserialize complex objects and arrays.
There is no way you can serialize methods (code).
For local storage persistence I would recommend Lawnchair.
no need to store in localStorage you can use global array any where in your application try this once
It's normally possible to serialise a method using myfunc.toString()
So, you could use a replacer function in JSON.stringify() and JSON.parse() to recognise methods, and call .toString() on them, and them somehow recognise them on parsing and turn them back into first class functions.
However - note that a reconstructed function will not have access to the original object's scope, i.e. private variables, or methods, etc.
e.g.
function A() {
var foo = 'bar';
this.test = function test() { console.log(foo) };
};
var b = new A();
var f = b.test.toString(); // the text of the method
b.test2 = new Function(f);
b.test2();
> undefined
well,
there is a way to convert object with functions to string and vise verse. take a look at this plugin:
http://www.eslinstructor.net/jsonfn/
good luck,
-Vadim
I'm using JSON to communicate some data through AJAX from the backend to the frontend (Javascript, of course). The XMLHttpRequest is done by a Prototypejs-written AJAX-handler (I'm still in the process of migrating to jQuery, but the noConflict-mode allows me to run both simultaneously), after which PHP sends the X-Json header with some data like objects = {'foo': 'bar'}.
The Prototypejs-Ajax.Request passes a json variable to the onSuccess-callback, containing all the JSONdata, so the processing isn't the hard part. However, I noticed that since the JSON is automatically evaluated, the objects variable is made global (and thus a member of the window object.
I know it's not really a problem since it's just an unused variable, but I always tried to stay away from global variables as much as possible. Additionally, the datasets may be pretty large on some occasions, so it'll just be a huge duplicate variable of which one is never used. So, if possible, I'd rather lose the global.
My question: how? If there's a good reason for this happening, or if this is just a Prototypejs-specific issue, or if this just indicates I'm doing something very wrong, please tell me :-)
Thanks!
Are you sending back objects = {"foo":"bar"} from PHP? When sending JSON, you just send {"foo":"bar"} and get the data as the return result of eval:
var json = '{"foo":"bar"}'; // This string would really be coming from PHP
// ...
var objects = eval('(' + json + ')'); // objects variable will be limited to the
// current scope.
If, for some reason, you must evaluate objects = ..., you can limit the variable to the current scope before running eval:
var objects;
eval('objects = {"foo":"bar"}');
Note that the PHP functions json_encode and json_decode will create "proper" JSON for you, which means it will use double quotes, and it will not use any kind of assignment (True JSON is limited to an array/object as the outer-most value, and it may not contain assignment or function calls. See the JSON specification.)
If the PHP is outputting objects = {'foo': 'bar'} then it isn't outputting JSON. JSON can't include the '=' character outside a string and uses the double quote character not the single quote. This means it is outputting JavaScript.
You have two options here.
The first is to try to restrict the scope of the JavaScript, the second is to fix the PHP so it outputs real JSON.
I would recommend the second option. Deal with JSON not JavaScript.
If you want to try to restrict it, then you need to limit the scope somehow. Possibly with:
function () {
eval("var " + php_generated_code);
doSomethingWith(object);
}
… although I'm not sure what the scope of eval() is.