The techniques "eval()" and "JSON.parse()" use mutually exclusive formats.
- With "eval()" parenthesis are required.
- With "JSON.parse()" parenthesis are forbidden.
Beware, there are "stringify()" functions that produce "eval" format. For ajax, you should use only the JSON format.
While "eval" incorporates the entire JavaScript language, JSON uses only a tiny subset of the language. Among the constructs in the JavaScript language that "eval" must recognize is the "Block statement" (a.k.a. "compound statement"); which is a pair or curly braces "{}" with some statements inside. But curly braces are also used in the syntax of object literals. The interpretation is differentiated by the context in which the code appears. Something might look like an object literal to you, but "eval" will see it as a compound statement.
In the JavaScript language, object literals occur to the right of an assignment.
var myObj = { ...some..code..here... };
Object literals don't occur on their own.
{ ...some..code..here... } // this looks like a compound statement
Going back to the OP's original question, asked in 2008, he inquired why the following fails in "eval()":
{ title: "One", key: "1" }
The answer is that it looks like a compound statement. To convert it into an object, you must put it into a context where a compound statement is impossible. That is done by putting parenthesis around it
( { title: "One", key: "1" } ) // not a compound statment, so must be object literal
The OP also asked why a similar statement did successfully eval:
[ { title: "One", key: "1" }, { title: "Two", key: "2" } ]
The same answer applies -- the curly braces are in a context where a compound statement is impossible. This is an array context, "[...]
", and arrays can contain objects, but they cannot contain statements.
Unlike "eval()", JSON is very limited in its capabilities. The limitation is intentional. The designer of JSON intended a minimalist subset of JavaScript, using only syntax that could appear on the right hand side of an assignment. So if you have some code that correctly parses in JSON...
var myVar = JSON.parse("...some...code...here...");
...that implies it will also legally parse on the right hand side of an assignment, like this..
var myVar = ...some..code..here... ;
But that is not the only restriction on JSON. The BNF language specification for JSON is very simple. For example, it does not allow for the use of single quotes to indicate strings (like JavaScript and Perl do) and it does not have a way to express a single character as a byte (like 'C' does). Unfortunately, it also does not allow comments (which would be really nice when creating configuration files). The upside of all those limitations is that parsing JSON is fast and offers no opportunity for code injection (a security threat).
Because of these limitations, JSON has no use for parenthesis. Consequently, a parenthesis in a JSON string is an illegal character.
Always use JSON format with ajax, for the following reasons:
- A typical ajax pipeline will be configured for JSON.
- The use of "eval()" will be criticised as a security risk.
As an example of an ajax pipeline, consider a program that involves a Node server and a jQuery client. The client program uses a jQuery call having the form $.ajax({dataType:'json',...etc.});
. JQuery creates a jqXHR object for later use, then packages and sends the associated request. The server accepts the request, processes it, and then is ready to respond. The server program will call the method res.json(data)
to package and send the response. Back at the client side, jQuery accepts the response, consults the associated jqXHR object, and processes the JSON formatted data. This all works without any need for manual data conversion. The response involves no explicit call to JSON.stringify() on the Node server, and no explicit call to JSON.parse() on the client; that's all handled for you.
The use of "eval" is associated with code injection security risks. You might think there is no way that can happen, but hackers can get quite creative. Also, "eval" is problematic for Javascript optimization.
If you do find yourself using a using a "stringify()" function, be aware that some functions with that name will create strings that are compatible with "eval" and not with JSON. For example, in Node, the following gives you function that creates strings in "eval" compatible format:
var stringify = require('node-stringify'); // generates eval() format
This can be useful, but unless you have a specific need, it's probably not what you want.