Converting JSONobj to Obj not working? - javascript

I'm attempting to convert a JSON object to a "normal" object using the following...
var slaobj = eval('('+s+')');
s being the JSON. however, it doesnt seem to work (It's `.length' is coming back as undefined). What am I doing wrong?

It's `.length' is coming back as undefined
It won't necessarily have a length property, unless it's an array or some other object that has one. For example:
var json = '{"foo": "Value of foo"}';
var obj = eval('(' + json + ')');
alert(obj.foo); // alerts "value of foo"
alert(obj.length); // alerts "undefined", there's no `length` in `obj`
Live example
Off-topic: Using eval to deserialize JSON text can be a security problem, unless you can unambiguously trust the source of the JSON text (for instance, it's your own server and you're connecting via SSL), because eval doesn't parse JSON, it parses and runs JavaScript code. (Adding the parentheses doesn't really help.) You can get alternatives to using eval from Douglas Crockford's Github page (he's the inventor of JSON). Last I checked, there are three alternatives there, two of which don't use eval at all; see the README at the bottom of the page for details.

Objects don't all have ".length" properties. An object literal like:
{ 'foo': 100, 'bar': 'Abraham Lincoln' }
describes an object that has no ".length" property.
JavaScript Array objects have ".length" properties because of the way the language runtime works. But a plain object in JavaScript only has such a property if you put it there.

How are you retrieving the object?
I would say there has to be something else wrong - are you sure the 's' JSON object was returned correctly?
JSON.org
To convert a JSON text into an object, you can use the eval() function. eval() invokes the JavaScript compiler. Since JSON is a proper subset of JavaScript, the compiler will correctly parse the text and produce an object structure. The text must be wrapped in parens to avoid tripping on an ambiguity in JavaScript's syntax.
var myObject = eval('(' + myJSONtext + ')');

Update: Ah, I see, that's what the parentheses are for. Rats. Deleted the first part.
But this remains valid:
Don't use eval!
eval() is a dangerous function, which
executes the code it's passed with the
privileges of the caller. If you run
eval() with a string that could be
affected by a malicious party, you may
end up running malicious code on the
user's machine with the permissions of
your webpage / extension. More
importantly, third party code can see
the scope in which eval() was invoked,
which can lead to possible attacks in
ways of which the similar Function is
not susceptible.
Source: Mozilla JavaScript Reference: eval()

http://www.jsonlint.com/ this site has good JSON string validation which you should have at your disposal all the times. It's good to validate the JSON string when its really big.
Also do not user the eval() to get the JSON object. Visit http://www.json.org/ it has really nice guide lines check it.
There are many JavaScript libraries today which offers JSON API. I will suggest you to user one of it for safety.
http://api.jquery.com/jQuery.getJSON/
http://developer.yahoo.com/yui/json/
http://dojotoolkit.org/reference-guide/dojo/_base/json.html

Related

What's the point of jQuery.parseJSON(JSON.stringify(someData));

Came across this snippet
var someDataJSON = jQuery.parseJSON(JSON.stringify(someData));
According to MDN the inner "method converts a JavaScript value to a JSON string"; then the outer method "Takes a well-formed JSON string and returns the resulting JavaScript value" per jQuery
If you start with a JS value & end up with a JS value, is this a pointless operation?
Usually that is a trick used to get a by-value copy of an object in javascript. (Since all objects are passed by reference). You can find a more in-depth answer on how to accomplish this, if you're curious, in this stackoverflow post
If someDataJSON is a flat JSON object, this way you get a copy of that object. Since, there is no direct method to copy a javascript object "by value" [and not "by reference"], this trick can be used.
var copyJSONObj = JSON.parse(JSON.stringify(JSONObj))
So, there is some point after all.

why can't I parse JSON without quotes in JS?

Why can't I parse the JSON object? I need to wrap it in quotes for parse to work.
// JSON object
var foo = {"sayHi": {"nl":"hoi", "en":"hello"}};
alert(foo.sayHi.en);
// string
var foo = '{"sayHi": {"nl":"hoi", "en":"hello"}}';
alert(JSON.parse(foo).sayHi.nl);
edit:
// does not work
var foo = {"sayHi": {"nl":"hoi", "en":"hello"}};
alert(JSON.parse(foo).sayHi.nl);
Yes, both work, but the first foo doesn't work the with parse. And I like the first foo better, because I don't need to worry about linebreaks, quotes and plus signs.
edit2:
I'm really looking for a nice way to store the JSON in a variable instead of using an ajax call to get it.
Because this {"sayHi": {"nl":"hoi", "en":"hello"}} is already js object
and this '{"sayHi": {"nl":"hoi", "en":"hello"}}' is just a string, containing whatever, maybe json
Depends on what you mean by "parse the JSON object" (which is not a thing by the way; JSON is a notation). If you want to parse it into an object then congratulations, you're done! JSON.parse takes a string using JSON (the notation) and turns it into an object in JavaScript (but many other languages can also parse JSON and turn it into respective data structures).
Both of your code snippets work as expected, though.

Passing RegExp objects between content scripts and main add-on script

I am having an issue whereby I create a RegExp object in a content script and pass it as part of an object back to the main script using self.port.emit().
Somewhere along the way it seems to lose its identity as a RegExp and also its toString abilities. The following returns false in the main script, but true in the content script:
Object.prototype.toString.call(regexp) == '[object RegExp]';
regexp instanceof RegExp;
Interestingly for Arrays passed in the same way the following is true:
Object.prototype.toString.call(array) == '[object Array]';
Am I missing something?
The Add-on SDK doesn't pass objects around when you send messages, only strings - it essentially calls JSON.stringify() on one side and then JSON.parse() on the other. The result is easy to predict:
console.log(JSON.stringify(new RegExp()));
This gives you "{}". In other words, JSON.stringify() treats "custom" objects as normal objects without any properties, object prototypes and such are ignored. What you get in your main code is a plain object, same as if you call new Object().
If you need to pass a regular expression to your main code - send regexp.source, create an actual regular expression on the other side. Sending actual objects around isn't possible.
What about if you just sent the regex pattern instead of the whole rexexp object? e.g. encodeURIComponent(regexp.source);

What is the correct way to "serialize" functions in javascript for later use

I have a "library" of objects that I want to load on the fly from a database. Each object comes with its own special functions that are called at specific times depending on the objects type. Ideally I'd like to be able to do this, although its been pointed out that this doesn't work:
library = {
"myObj" : {"name" : "myObj", "type" : "myType", "function" : function () { } } //, etc
}
The string "myObj" is passed around my program quite a bit, but I only have to access certain values of the object at a time, and in some circumstances there's a specific function that needs to be run. The problem is that I'm looking at hundreds, and eventually thousands, of potential objects that could exist with varying functions.
What is the "right" way to store a function to be called like this. I know that calling eval can be very unsafe during execution, enabling xss attacks and whatnot. I really want to avoid a massive switch statement or the bloated loading of additional functions. I'd also like the solution to be as concise as possible.
This can't be the first time this has come up. ;/
Thanks for your help.
Just use eval to recreate the function after loading it as a string. So if you deserialize an object myObj from JSON, and you have a property:
myObj = {
....
function: "function() { ... }"
}
you can very easily turn it to a real function:
eval("myObj.func = " + myObj.func);
http://jsfiddle.net/kceTr/
Oh - I am not sure if that was an edit or I missed it before - but re: eval.
Eval is a tool. You want to store a function in a database. It really doesn't make much difference if you have to "eval" to turn it into code, or there was some other magic way to do it: if someone can change the data in your DB, then they can change a function.
If you need to store a function, then eval is your tool. It's not "bad" by nature, it's bad because it's easy to misuse. Whether you use it well or not is up to you.
Remember anything running on the client is still just running on the client. There's nothing a malicious person could do with eval, that they couldn't do with the Chrome debugger a lot more easily. Anyone can always run any code they want on the client, it's up to your server to decide how to handle what it receives. There's nothing safe on the client in the first place...
Changing the prototype of the object is a half thought I have.
You've got your library like
library = {
"myObj" : {"name" : "myObj", "type" : "myType", "function" : function () { } } //, etc
}
You've got an object (let's call it theObj) that you know is a myObj (due to a string maybe? property?)
theObj.__proto__ = library["myObj"];
That way you can execute
theObj.function(...);
jsfiddle example (it's rough!). Also, be careful with proto, it's deprecated (1) (2)
As to serializing the functions, can you get them in using a script tag that points to something serverside that slurps them from the db and returns the js? Just include them inline as you render the page (in a script block)? Or, if all else fails, eval should work, as long as you know that the functions you've got stored in the database are clean and safe.
There is no right way to do this, because its not generally a good idea.
HOWEVER, if you want to do it anyways you can simply extend the prototype of Function with a .toJSON method.
Function.prototype.toJSON = function(){ return this.toString(); }
Then you can simply use JSON.stringify and functions will be serialized as strings.
Its generally a not good idea in most cases. There are very few circumstances where you want to do this and even then, there is probably a better way.
A better approach might be to serialize the object's properties when you "sleep" it, and "waking" the object by reattaching its properties to a new instance of the object with the appropriate methods defined.
what you are doing with it is just fine. However, if i were you, for readability and tidyness, i would rather have the function created outside and simply have it assigned to your object key.
You don't need eval here. Instead do it this way whenever you want access to the stored function -
library.myObj.function()
You do your best in parameterising your functions, so that you end up
with as little typologies as possible.
Store them on the server in individual JS files, then load the needed file dynamically, by name.
In the JSON, only store the name of the file that contains the function that you need. And, of course, you will be caching already loaded files, to go easy on the server.
Just my two cents.
You can only really serialise a whole file with require calls in it. If you do that, you can create a module, exports and module.exports, eval the file with a function surrounding it and snag the module.exports out of it.
It's not exactly secure, but for that you need to use something like VM2 and value-censorship (which I've been working on) to avoid them calling eval() and owning your machine or the entire network.

How to get Javascript Objects from JavaScriptSerializer?

When I use the System.Web.Script.Serialization.JavaScriptSerializer.Serialize method, I get back valid JSON code.
This is usually perfect, but sometimes I want to get back the result as a Javascript object, not JSON. The Serialize method has an overload that takes a SerializationFormat parameter. That looks perfect... but it is marked as internal!
How can I get out a string of Javascript from the Serializer?
Take a look at the JScript DLL Eval object's JScriptEvaluate method (http://msdn.microsoft.com/en-us/library/microsoft.jscript.eval.jscriptevaluate.aspx):
using Microsoft.JScript;
var MyJSObject = Eval.JScriptEvaluate("{a:'Property1',b:'Property2'}", Engine);

Categories

Resources