JSON Is not JavaScript

Andrew Crites
5 min readMay 2, 2015

--

(and JavaScript is not JSON)

You don’t have to spend much time on Stackoverflow before you find someone saying something like

I have JSON like {key: value}. How do I access value?

It won’t take long before a pedant points out that a JavaScript object (either an object literal or an object derived from some other code) is not JSON. I am more than happy to be one of those pedants as well.

Misnomer

While the vast majority of examples of JSON I’ve seen use objects or arrays, this is not a requirement. The below examples are all valid JSON.

  • 2
  • true
  • false
  • null
  • "this is a string"

It should be obvious to anyone familiar with JSON that none of these are objects. However, JSON.parse('2') will happily extract the number "2." Without getting into an argument about whether or not 2 can be considered an object in some circumstances, it is not an object literal in JavaScript.

Note: it’s probably worth noting that “nothing” is not valid JSON. Many JSON parsers will complain when parsing an empty string, e.g. JSON.parse("")

Still, I think that JSON is a good name. It’s easy to pronounce, and it was at least inspired by JavaScript Object literal syntax. Regardless, referring to a JavaScript object as JSON is not correct. It’s idiomatic to refer to a string containing valid JSON as “JSON.” “JSON string” may be more accurate, but I’ve tossed the phrase “parse xml” around when I was talking about a string in plenty of cases.

This doesn’t mean that JSON has to be a string either. It’s a notation — an idea. It’s just convenient to refer to a construct that you can successfully use JSON.parse on as "JSON."

Who’s to blame?

Usually in the context of JavaScript code when people refer to JSON what they actually mean is a JavaScript object (or just “Object” to avoid redundancy). While it is true that JSON can be parsed into a JavaScript object in some circumstances, this doesn’t mean that they are analogous. Part of the confusion does stem from documentation including the RFC (4627) that actually names the thing JavaScript Object Notation.

Another source of the problem is probably the monster jQuery. When I say “monster” I am referring to its meteoric rise to fame and its ability to influence the JavaScript community and new developers. I happen to love the library.

jQuery will conveniently black box the parsing of JSON in some circumstances. For instance, if valid JSON is received from a request via $.getJSON, jQuery will parse it behind the scenes and the response returned to the successf callback function will already be parsed. As I've said this is almost always a JavaScript object, so one could easily think that this is just what JSON is and how it works. AngularJS and its $http service and other libraries often handle JSON returned from web services in a similar way.

This can actually lead to confusion if one assumes that jQuery will only return a request raw. The below will explode horribly (it would if using JSON.parse for the same reason). JavaScript will attempt to convert the already parsed data in json to a string that is obviously not valid JSON.

This could lead to a Stackoverflow question from a confused user. They will quickly get comments about how everything should work if they just remove the line containing $.parseJSON. However, their variable will still be named json even though it's not JSON. Not by any standard -- nor was it ever. Still, their code refers to it as json, other perhaps even less experienced developers will think of it as JSON, and the cycle continues.

When JavaScript is not JSON (and vice versa)

There are plenty of circumstances where JavaScript is not valid JSON.

There are also circumstances where JSON is not valid JavaScript. In fact, since JavaScript does not support bare objects, the simple statement {"k":"v"} will emit an error in JavaScript (go ahead and try it in your browser console) whereas it can be parsed as valid JSON. However, the expression ({"k":"v"}) is valid (albeit it useless). The parentheses turn the code into an expression that can be evaluated. This is similar to why you need = or parens to immediately invoke a function from its declaration.

At this point many readers may be saying, “so what” (and knowing developers, plenty are probably saying, “so true.”) I don’t have a great answer for that. If you can correctly point out when JavaScript is not JSON you might feel some sense of superiority over others who may not recognize this fact so readily.

In defense of the JavaScript vs. JSON recognition argument, I think that clarity and consistency are important — especially in the software development world. You shouldn’t call something something when it isn’t something. You should call it what it is. It’s also important to know what makes valid JSON vs. JavaScript because it’s quite likely that if you have to work with one you will have to work with the other.

JSONP is not JSON

Adding to the confusion is the existence of JSONP. Now that the awesome power of CORS is available, JSONP is quickly dying, but as long as XDomainRequest is required by IE8 and IE9, we’ll be held back.

JSONP is called “JSON with padding,” so it only serves to further the confusion. In fact, JSONP is not JSON and it doesn’t even have anything to do with JSON. Incidentally valid JSON will work when JSONP is used correctly, but this is not even a requirement.

JSONP is actually JavaScript. In fact, the recommended content type for the response is application/javascript. Ostensibly there is a proposal that application/json-p be used for security reasons, but as far as I know this content type is not actually implemented and probably never will be.

A JSONP response needs to be valid JavaScript because it is actually run as JavaScript. As discussed above, a valid JSON response and valid JavaScript are generally incompatible.

Even though the object that is the argument of the callback above could have been written as valid JSON (i.e. with notation that could be parsed via JSON.parse) it's not. It will still run just fine after a JSONP request.

This can lead to a tremendous amount of confusion — perhaps even more than jQuery’s automatic parsing. Attempting a jsonp request and getting a JSON response will lead to the potentially confusing error

SyntaxError: Unexpected token :

To the uninitiated this could seem like all kinds of problems.

  • The unexpected token is a non-printing character
  • There is an issue with the server and it’s not sending back valid JSON (it shouldn’t be for a JSONP request anyway).
  • There’s a syntax error in the client script.

I could go on, but the point is that confusing names and a lack of good standardization for JSONP can make debugging hell. This may seem like a contrived circumstance, but it actually happened to my team yesterday. Fortunately, I immediately recognized the problem and was able to clear it up.

Even though the confusion many have between JSON and JavaScript Objects may not be that big of a deal, JSON vs. JSONP is a huge deal. It would make a lot more sense if it were called script tag injection, which is what it is, but the “injection” bogeyman would not make this term very marketable. It would also have the same initialism as “sexually transmitted infection.” Actually, that may make the name more accurate than anything having to do with JSON.

Originally published at blog.explosion-pills.com on May 2, 2015.

--

--