Eval doesn't work - JavaScript - javascript

I've never used eval() before, so I assume that I just got the syntax horribly wrong. What's wrong with the following:
var JSONAsString = '{"item1":"one", "item2":"two", "item3":"three"}';
var JSONAsObject = eval(JSONString);
alert(JSONAsObject.item1);
Since it doesn't seem to be working - I load the page and nothing happens.
And yes, I know I shouldn't be using eval. I assume that the syntax for JSON.parse() is the same as that of eval... right? If it is, if (after fixing the code) I replace eval with JSON.parse, will it still do the same thing?

When using eval you need to wrap the JSON in ():
var JSONAsString = '{"item1":"one", "item2":"two", "item3":"three"}';
var JSONAsObject = eval('(' + JSONAsString + ')');
alert(JSONAsObject.item1);
However, you should use JSON.parse() right from the beginning, not just later. Otherwise possibly invalid JSON that is valid JavaScript might work but stop working when switching to JSON.parse.
Note that you should include json2.js when using JSON.* since some older browser do not have native JSON support.

Don't use eval() to parse JSON. Use Douglas Crockfords json2, which gives you cross-browser support, performance and security: https://github.com/douglascrockford/JSON-js

Related

Why use JSON.parse(decodeURIComponent(staticString))?

Certain dynamic web frameworks use this code fragment
<script>
appSettings = JSON.parse(
decodeURIComponent(
"%7B%22setting1%22%3A%22foo%22%2C%22setting2%22%3A123%7D"));
</script>
Is there a standard HTML5/JavaScript problem are they trying to solve with this code. Why not just
<script>
appSettings = {"setting1":"foo","setting2":123};
</script>
Note: this is dynamically generated code. I'm assuming on the server they are doing something like
var settingsString = encodeURIComponent(JSON.stringify(settings));
var output = '<script>appSettings=JSON.parse(decodeURIComponent("' +
settingsString +
'"));</script>';
But it seems like it would work just as well like this
var settingsString = JSON.stringify(settings);
var output = '<script>appSettings=' +
settingsString +
';</script>';
One idea is the latter could contain code but they are the ones providing the string, it's not user data so they're no chance it could be code. Plus using JSON.stringify on the server would remove all code. On the client even then a simple JSON.parse of a JSON.stringifyied object would prevent code.
Is there a concrete problem being solved by the triple parsing? Once by JavaScript, once by decodeURIComponent, once by JSON.parse?
THIS IS NOT AN OPINION BASED QUESTION
The question is what problem is being solved. Either there is a problem being solved or there is not. No opinions required to answer that question. For example if JSON.stringify happens to emit unparseable code sometimes (which as far I know it doesn't but if someone knows better then that would be a good answer as to why).
Also note: I'm not asking why their framework does this. I'm asking if there is real problem being solved in standard HTML5/JavaScript. In other words, should I adopt this pattern because I'm going to run into an issue someday if I don't.
Is there a concrete problem being solved by the triple parsing?
Yes. Your suggested solution has two problems:
It's parsed as HTML. Things like </script> can cause havoc in an inline script.
It's parsed as JS. Not all JSON strings are valid JS literals.
The decodeURIComponent + JSON.parse approach is a crude workaround however and looks more like a quick fix than a proper solution.
#katspaugh is correct
Testing
var settingString = JSON.stringify({
"</script>": "<script>bar=123</script>",
});
Generates the code for the above example as
<script>
appSettings = {"</script>":"<script>window.bar=123</script>"}
</script>
Which fails to parse as HTML. Adding the encodeURIComponent on the server JSON.parse(decodeURIComponent(...)) on the client fixes that issue
DO NOT USE IT.
let str = `C:\\Users\\Administrator\\Desktop\\小灶\\GT4T_translated_Chinese Simplified (简体中文)\\2013\%2F193461.pdf`
let newStr = decodeURIComponent(JSON.parse(`"${str}"`))
Depending on the str content, you may get unexpected errors. The code above will cause this error:
SyntaxError: Unexpected token U in JSON at position 4

Difference between angular.fromJson and $scope.$eval when applied to JSON string

In my angularjs apps, I usually parse a JSON string by using angular.fromJson, like so:
var myObject=angular.fromJSON(jsonString);
However, it seems that I would obtain the same result by using $scope.$eval:
var myObject=$scope.$eval(jsonString);
See this fiddle
Or by using vanilla javaScript, like so:
var myObject=JSON.parse(jsonString);
Is there any particular reason to use angular.fromJSON rather than JSON.parse?
Is there any possible issue when using $scope.$eval to parse a JSON string?
Check out the source code:
function fromJson(json) {
return isString(json)
? JSON.parse(json)
: json;
}
They're just passing through to JSON.parse.
As for $eval it shells out to $parse:
// $scope.$eval source:
$eval: function(expr, locals) {
return $parse(expr)(this, locals);
},
$parse source is too long to post, but it is essentially capable of converting inline (stringified) objects to real Objects and so it makes sense that in this case, it will actually convert your JSON as well.
(I did not know this until reading through the $parse source just now.)
Is there any particular reason to use angular.fromJSON rather than JSON.parse?
Nope, not really. Although they do check to you to ensure that you don't double-parse a JSON string, like so:
var jsonString = '{"foo":"bar"}';
var json = JSON.parse(jsonString); // Parsing once is good :)
JSON.parse(json); // Parsing twice is bad :(
Is there any possible issue when using $scope.$eval to parse a JSON string?
I don't think so off the top of my head, other than that you're doing more work than is necessary. So if you know you have JSON, there's no reason to use the heavier $parse function.
The above answer is almost correct. However, there is a potential issue with using $scope.$eval() to parse a JSON string, which does not exist with either JSON.parse() or angular.fromJson(): security. Angular allows an expression to contain complex JavaScript including function calls, conditionals with ?:, variable assignments, and so on. All of these are recognised and processed if you use $scope.$eval(), even if they were added by a malicious end-user.
JSON does not support any of those more complex JavaScript features, nor anything else potentially "dangerous". If you use a true JSON parser like JSON.parse() or angular.fromJson(), there is no chance of malicious code being injected and executed.
Since Angular expressions are isolated and evaluate only in the current $scope, the risk of code injection is somewhat mitigated - $scope.$eval() is far less dangerous than JavaScript's native eval() for parsing JSON. However there is still no reason to use either function for this purpose, since there is a potential security risk and using a proper JSON parser is likely to be faster.

JSON mapping in Javascript

So I have this JSON
https://bitcoinpayflow.com/orders{"order":{"bitcoin_address":"1NwKSH1DJHhobCeuwxNqdMjK5oVEZBFWbk"}}
No I want to reference the bitcoin_address
So first I strip away the string at the beginning
var stripped = data.substring(33);
alert(stripped);
var btc = stripped.orders.bitcoin_address;
alert(btc);
I get the first alert, but not the second. Any idea why?
Because stripped is still just a string. You need to parse it into an object. You can use the native JSON.parse method to do this:
var stripped = JSON.parse(data.substring(33));
Also, you are referencing the orders property, which doesn't exist. It's order.
Note that JSON.parse is not supported by older browsers. You can use this polyfill to make sure it's always available.
The easiest way to decode json - string - use eval
var bitcoins = eval('(' + json_string + ')');
And access bitcoins['order']['bitcoin_address']
But it a bit unsafe. Upper method is more safer.
I would use JSON.parse as follows.
$.post('php/whatever.php',{data:dS},function(res){
var o=JSON.parse(res);
var bitcoins=o.order.bitcoinaddress;
},"text");

Parsing JSON with Javascript

I have this JSon string received from an AJAX call:
{status:OK,addresses:[0,1,2,3,4,5]}
To convert it to a JSon object I have this line:
var jsonObj = eval(jsonString);
But an exception is thrown! This one has no message in the exception variable.
I also tried using
{"status":"OK","addresses":[0,1,2,3,4,5]}
And, yet again, an exception is thrown but saying that an unexpected character '&' was found.
I'm using Struts2 and the JSon is received from an action.
Any help will be appreciated.
Thank you
{status:OK,addresses:[0,1,2,3,4,5]}
is not valid JSON because the quotes around status and addresses are missing, and is neither valid JSON nor valid JavaScript since the quotes around OK are missing.
Also, don't use eval to parse JSON - it allows an attacker to execute arbitrary JavaScript in the context of your page. Instead, use the safe alternatives JSON.parse(built-in in modern browsers and other EcmaScript 5 implementations) or JSON2.
Don't use eval: use a proper JSON parser such as JSON2.
You probably have extra content in the response: check that you are not printing anything else out.
This is working for me:
JSON.parse('{ "status" : "OK", "addresses" : [0,1,2,3,4,5]}');
If you want to use eval, then you need to use the second example you posted ({"status":"OK","addresses":[0,1,2,3,4,5]}) and you need to surround the string with parenthesis as such:
var jsonObj = eval( '('+jsonString+')' );
This makes jsonString a valid javascript statement.
With that being said, I encourage you use JSON.parse, as many others have posted. It is far more secure.
You don't have a JSON string. You do have an object literal. You need the names to have quotes.
{"status":OK, "addresses":[0,1,2,3,4,5]}
Based on this comment:
So I verified that when JSon is received from the request, all the " are replaced by " ... could this be the problem?
Yes. A JSON parser expects to receive JSON as input, not HTML encoded JSON.
Two issues to fix:
Add quotes around the "OK" to make it a legal javascript string.
Add parens around the string before sending to eval like this eval("(" + jsonString + ")")';
This:
{status:OK,addresses:[0,1,2,3,4,5]}
would have to be changed to this:
{status:"OK",addresses:[0,1,2,3,4,5]}
to be valid Javascript (note the quotes around "OK").
It should be this to be valid JSON (quotes around the keys too):
{"status":"OK", "addresses":[0,1,2,3,4,5]}
OK all by itself is not a known piece of Javascript without the quotes around it to make it into a Javascript string. In the future, you can test yourself in a small test bed and see what the error is in your favorite javascript debugger:
http://jsfiddle.net/jfriend00/FcSKR/
var jsonString = '{"status":"OK","addresses":[0,1,2,3,4,5]}';
var jsonObj = eval("(" + jsonString + ")");
alert("success");
If you still get an error with {"status":"OK","addresses":[0,1,2,3,4,5]} and the adding of parens before sending to eval, then your data isn't what you think it is and you need to do some debugging to see exactly what is in the response (look at the value in the debugger, put the value into an alert, etc...). There is probably some other stuff in the response that you didn't know would be there.
Note: there are some situations where a JSON parser like JSON.parse() and a legal JSON string is safer than eval() with Javascript that can be anything.

How to parse JSON in JavaScript to take value

I am really stuck in parsing a JSON string and take it's values. I got the JSON string as
{"user":{"id":"1","firstname":"Freelogin","created":"0000-00-00 00:00:00","lastname":"Administrator","email":"fred#websecurify.com", "usergroup_id":"1","status":"1","ip_enable":"N","priv":"0","expire":""},"data":{ "1":{"5":{"last_update":"2010-12-13 16:16:16","status":"0"},"3":{"last_update":"2010-12-13 16:41:48","status":"1"}},"2":{"6":{"last_update":"2010-12-13 16:41:48","status":"1"}}},"server_array":[{"id":"1","name":"anes.yyy.net"},{ "id":"2","name":"neseema.xxx.net"}],"service_array":[{"id":"5","name":"POP3"}, {"id":"6","name":"Cpanel"},{"id":"3","name":"SMTP"}],"sort_by":"servername", "sort_order":"ASC","pagelinks":"","totrows":"2","offset":"0","limitvalue":"10", "rows_monitor":2,"current":"monitor","uri":false}
How to Parse this and take the Results for further
processing in JavaScript
You should use jQuery.parseJSON. It will use native JSON if available, and only use eval if necessary, after a sanity check.
Use JSON.parse (redirected from http://json.org), alternatively MDN
Json is already some javascript. so parsing is just using eval
like:
var foobar = eval(yourjson);
alert(foobar.user);
Also jquery has some function for it jquery.parseJSON
like:
var foobar = $.parseJSON(yourjson);
Jquery is better because it would make some checks and perform better.
First, download jQuery.
Second, include it in your page.
Third, if your variable is this:
var jsonString = '{"user":{"id":"1","firstname":"Freelogin","created":"0000-00-00 00:00:00","lastname":"Administrator","email":"fred#websecurify.com", "usergroup_id":"1","status":"1","ip_enable":"N","priv":"0","expire":""},"data":{ "1":{"5":{"last_update":"2010-12-13 16:16:16","status":"0"},"3":{"last_update":"2010-12-13 16:41:48","status":"1"}},"2":{"6":{"last_update":"2010-12-13 16:41:48","status":"1"}}},"server_array":[{"id":"1","name":"anes.yyy.net"},{ "id":"2","name":"neseema.xxx.net"}],"service_array":[{"id":"5","name":"POP3"}, {"id":"6","name":"Cpanel"},{"id":"3","name":"SMTP"}],"sort_by":"servername", "sort_order":"ASC","pagelinks":"","totrows":"2","offset":"0","limitvalue":"10", "rows_monitor":2,"current":"monitor","uri":false}';
then,
var parsedJson = jQuery.parseJSON(jsonString);
will give you the desired parsed object that's ready for manipulation.
I tried out your JSON string on JSONLint and it says it's valid, so you should have no problems with it.
you probably got your json in som String variable
var json = '{"user":{"id":"1","firstname":"Freelogin","created":"0000-00-00 00:00:00","lastname":"Administrator","email":"fred#websecurify.com", "usergroup_id":"1","status":"1","ip_enable":"N","priv":"0","expire":""},"data":{ "1":{"5":{"last_update":"2010-12-13 16:16:16","status":"0"},"3":{"last_update":"2010-12-13 16:41:48","status":"1"}},"2":{"6":{"last_update":"2010-12-13 16:41:48","status":"1"}}},"server_array":[{"id":"1","name":"anes.yyy.net"},{ "id":"2","name":"neseema.xxx.net"}],"service_array":[{"id":"5","name":"POP3"}, {"id":"6","name":"Cpanel"},{"id":"3","name":"SMTP"}],"sort_by":"servername", "sort_order":"ASC","pagelinks":"","totrows":"2","offset":"0","limitvalue":"10", "rows_monitor":2,"current":"monitor","uri":false}';
now you can easily parse it via jQuery (you also can parse it via native javaScript eval, but there are some security issues, badly formated input string f.e., that is covered with jQuery and not in eval)
result = jQuery.parseJSON(json);
Now you can easily acces your json object
alert('Hello user, your name is ' + json.user.firstname);
You don't need jQuery, in ECMAScript5 JSON object will be supported natively and with it you can use JSON.parse method to parse a string into a JS object. IE9 will support ES5 and FF and Chrome already do.
For the moment you can use json2.js (you can look at the source here) as fallback for the browsers that don't support JSON natively.

Categories

Resources