Or, is the result of 1/0 ‘Infinity’, as this science called mathematics is telling us?
In any case and at this moment in time, and looking into this JSON conundrum, I started to think I had no idea.
[first published 2013 JAN 01]
Consider for example this little “number” :
1 2 3 4 5 6 7 |
document.writeln( JSON.stringify( { a: 2, b: undefined }) ); |
Produces
1 |
{ "a" : 2 } |
Property “b” is simply and quietly not created, or so it seems? Perhaps it is me who is wrong or I need to go way back to ES5 specification?
JSON NOT to rescue
The problem is not in some esoteric ES5 “feature” (aka omission) but it is an “issue” with JSON. JSON [RFC8259] was created to ignore undefined (and functions, NaN’s and Infinity-es). And yes I knew this. I started this post in this way because I also wanted to show how this kind of “feature” can catch anybody off-guard. And repeatedly at that. In the snippet above there is yet another fundamental rule of JavaScript/DOM programming broken:
Never use
JSON.stringify()
for debugging
Object literal above is not a mistake. It really produces an object with properties “a” and “b”, where “b” is indeed undefined. And crucially key “b” does exist, and its value is undefined. So, back to senses, hit F12 in your venerable Chrome or IE, and try this:
1 2 3 4 5 |
console.dir( { a: 2, b: undefined }) |
And voila, the output is the actual object created, with two properties present:
1 2 3 4 |
Object a: 2 b: undefined __proto__: Object |
Not out of this wood, yet
This might be one happy ending to one blog post, but alas it is not. Far from that. The big worm in that can is this: How is this reflected on AJAX? How are XMLHttpRequest implementations out there handling this JSON “feature”? Namely: how is one passing JSON objects where some keys might have values as e.g. undefined? JSON encoded object like this one:
1 |
'{ "a" : 2, "b" : undefined }' |
is of course NOT a good JSON and the resident JSON.parse()
method on the receiving side will throw a syntax error:
SyntaxError: Unexpected token
If anybody cares: (2014 SEP 11 Update ) In IE11 Console for some reason this is "Invalid character", Error
? In case you are laughing at mentioning IE, here is the Opera response as of today (2021 MAR)
1 2 3 |
VM5325:1 Uncaught SyntaxError: Unexpected token u in JSON at position 17 at JSON.parse (<anonymous>) at <anonymous>:1:6 |
Many years have passed. It seems we have no solution yet.
I am not even sure I can hope that the sending side (in the wild there are very strange senders) will allow me to come to the above point where I can use JavaScript code, and conclude something is wrong with the JSON “arrived from afar”. And instead of blaming them senders:
I am not sure how to pack the offending object into a valid JSON string, that can be parsed safely.
So, what gives? I see no other way but to perhaps use ‘null’ instead of undefined’? But then I have no simple/native/natural way of JSON trustingly encoding the object which (for example) represents the calculation of the table from the image in this post ). if x is zero then 1/x is not ‘null’. It is mathematically to be represented as ‘infinity’, not as ‘null’, and not as undefined
I repeat: not as “undefined” either. That table is from a reputable online fountain of knowledge, and that image is wrong. 1/0 is Infinity, not undefined
. Also, JSON encoding rules do not allow that too: Infinity is not a legal value in JSON. Should we try with undefined
:
1 2 3 4 5 6 7 8 |
// Chrome 90.0.4430.85, also IE11 (2014SEP11) // produce this kind of delicious // desert for ECMA deep divers to enjoy // and endlessly debate about // 2021 APR: yes Type Script is the same undefined == null // => true undefined === null // => false |
ECMA zealots argue: “Undefined is null but its identity is not null!”. Sane people (still left) reply: “null is not undefined and undefined has no identity!”. In any case, we are definitely not in the “good parts” of JavaScript, territory here. Let us proceed quietly.
In pure JavaScript, I can compute NaN or Infinity values or hold undefined ones, but how do I express in JSON that something is undefined, Infinity or NaN
?
Beside putting it in a string: “undefined”, “NaN”, “Infinity”. NaN
, undefined
and null
is three distinctive values. And just like any other values in JavaScript
1 2 3 4 |
// ECMA NaN + "" // => string'NaN' undefined + "" // => string 'undefined' null + "" // => string 'null' |
Solution? Direction? Perhaps, but solution no.
One could argue against code on the sending side that is putting these “offending values” into JSON, but that is a very “slippery slope” and no consistent standard does that. If I have to “decode” these strings into values on the receiving side, this introduces yet another level of encoding of “special” values and that is not a good thing. Not at all.
RFC8259: “The JavaScript Object Notation (JSON) Data Interchange Format”, December 2017
2 thoughts on “JSON: How to create an undefined or NaN value?”
You could have a getter that returns undefined?
Hi BLR , care to comment seven years after :)
I see no fundamental change in the “decision-makers” attitude on this issue.