JSON left out Infinity and NaN; JSON status in ECMAScript?

Viewed 89477

Any idea why JSON left out NaN and +/- Infinity? It puts Javascript in the strange situation where objects that would otherwise be serializable, are not, if they contain NaN or +/- infinity values.

Looks like this has been cast in stone: see RFC4627 and ECMA-262 (section 24.5.2, JSON.stringify, NOTE 4, page 683 of the ECMA-262 pdf at last edit):

Finite numbers are stringified as if by calling ToString(number). NaN and Infinity regardless of sign are represented as the String null.

10 Answers

The reason is stated on page ii in Standard ECMA-404 The JSON Data Interchange Syntax, 1st Edition

JSON is agnostic about numbers. In any programming language, there can be a variety of number types of various capacities and complements, fixed or floating, binary or decimal. That can make interchange between different programming languages difficult. JSON instead offers only the representation of numbers that humans use: a sequence of digits. All programming languages know how to make sense of digit sequences even if they disagree on internal representations. That is enough to allow interchange.

The reason is not, as many have claimed, due to the representations of NaN and Infinity ECMA script. Simplicity is a core design principle of JSON.

Because it is so simple, it is not expected that the JSON grammar will ever change. This gives JSON, as a foundational notation, tremendous stability

JSON5 allows standard Javascript notation for positive and negative infinity, NaN, and numerous other things that are valid ECMAScript that were left out of JSON (trailing commas, etc.).

https://json5.org/

This makes JSON a much more useful format.

However, whether using JSON or JSON5: for security reasons, always always parse -- don't evaluate!!

Potential work-around for cases like {"key":Infinity}:

JSON.parse(theString.replace(/":(Infinity|-IsNaN)/g, '":"{{$1}}"'), function(k, v) {
   if (v === '{{Infinity}}') return Infinity;
   else if (v === '{{-Infinity}}') return -Infinity;
   else if (v === '{{NaN}}') return NaN;
   return v;
   });

The general idea is to replace occurences of invalid values with a string we will recognize when parsing and replace it back with the appropriate JavaScript representation.

Related