9

I am passing null to JSON.parse() and although the first parameter is documented saying that it should be a string value, it still works to supply null.

How come this does not throw an error even though even though the documentation state this is for strings and can this be safely and reliable used in multiple browsers?

Stephan-v
  • 19,255
  • 31
  • 115
  • 201
  • check the below answer https://stackoverflow.com/questions/21120999/representing-null-in-json – Suvethan Nantha Sep 28 '17 at 08:32
  • I feel like that question is different since it talks about using `null` within JSON objects. JSON objects that `JSON.stringify` has gone over resulting in strings. I simply throw `null` into my `JSON.parse()` directly. – Stephan-v Sep 28 '17 at 08:34
  • I assume `parse` might internally cast the given value to a string, which would be `"null"`, which is a valid JSON value. – deceze Sep 28 '17 at 08:34
  • Ok if that is the case I wonder how reliable this is `cross-browser`. – Stephan-v Sep 28 '17 at 08:36
  • JSON.parse("null") or JSON.parse(null) both of them are casted as "null" which is a valid json, but if you pass JSON.parse('') it will throw an exception it's an empty string – Suvethan Nantha Sep 28 '17 at 08:42

2 Answers2

9

The ECMAScript spec says as the first step for JSON.parse:

  1. Let JText be ToString(text).

Meaning it'll cast whatever argument it's given to a string, and null casts to "null", which is the valid JSON representation of null.

Note that a single such JSON primitive shouldn't be valid, a JSON string should be wrapped in an object or array. But parsers have traditionally been lax with that, partially due to it making the implementation simpler I suppose.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • 1
    So I guess the most reliable thing to do here is check the input value to be a string before handing it over to `JSON.parse` since I am abusing it otherwise? – Stephan-v Sep 28 '17 at 08:43
  • 1
    "a JSON string should be wrapped in an object or array" — The original JSON specification said that, but not very clearly. [rfc7159](https://tools.ietf.org/html/rfc7159) updates it to say: A JSON text is a serialized value. Note that certain previous specifications of JSON constrained a JSON text to be an object or an array. – Quentin Sep 28 '17 at 08:43
  • @Quentin A case of the spec trailing the implementation, I suppose? – deceze Sep 28 '17 at 08:44
  • I wouldn't be surprised. – Quentin Sep 28 '17 at 08:45
  • @Stephan I would say you should *know* what values you're working with to begin with. If you have a `null` value where you should have a string, something's wrong in your code. More broadly you might want to `try..catch` any and all `JSON.parse` calls if you expect your JSON may be invalid in any way. – deceze Sep 28 '17 at 08:45
  • 1
    Well I know for certain the value is always a `string` or a `null` that I am supplying. Since `JSON.parse` accepts both they are not really invalid. I guess it is not 'proper' to hand it over a null value though. – Stephan-v Sep 28 '17 at 08:49
  • 1
    @Stephan A `null` value basically means "no value", in which case your code indeed shouldn't even go into the branch where it tries to parse "no value" as JSON but instead go do something else. – deceze Sep 28 '17 at 08:51
  • True. Thanks for helping out. – Stephan-v Sep 28 '17 at 08:52
  • intersingly the node.js JSON allows a Buffer to be parsed, presumably because the default toString for a buffer is utf8, which, assuming the buffer contains valid JSON, works. this means JSON.parse(fs.readFileSync('./package.json')) works fine. – unsynchronized Jun 21 '21 at 01:37
0

See the specification:

  1. Let JText be ToString(text).

It doesn't require that the first argument be a string, it attempts to convert it to a string.

"" + null will give you "null" which is a string containing valid JSON.

This is also in the spec:

Null: Return "null".

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335