Serialization of NaN and Infinity in JSON. Why not supported?
Per RFC 7159 - The JavaScript Object Notation (JSON) Data Interchange Format
Numeric values that cannot be represented in the grammar below (such as Infinity and NaN) are not permitted.
I would speculate that this is because NaN
and Infinity
don't actually represent numbers and/or can't be represented by any type of numeric format.
Force JSON.stringify() to emit NaN / Infinity or JS JSON lib that does so
Here is an example
Javascript
var array1 = [-Infinity, -1, 0, 1, 2, NaN, 4, 5, Infinity],
json = JSON.stringify(array1, function (key, value) {
if (value !== value) {
return 'NaN';
}
if (value === Infinity) {
return 'Infinity';
}
if (value === -Infinity) {
return '-Infinity';
}
return value;
}),
array2 = JSON.parse(json, function (key, value) {
if (value === 'NaN') {
return NaN;
}
if (value === 'Infinity') {
return Infinity;
}
if (value === '-Infinity') {
return -Infinity;
}
return value;
});
console.log(json);
console.log(array2);
Output
["-Infinity",-1,0,1,2,"NaN",4,5,"Infinity"]
[-Infinity, -1, 0, 1, 2, NaN, 4, 5, Infinity]
References
JSON.stringify
JSON.parse
On jsFiddle
Update:
Javascript
var array1 = [-Infinity, -1, 0, 1, 2, NaN, 4, 5, Infinity],
json = JSON.stringify(array1, function (key, value) {
if (value !== value) {
return '0/0';
}
if (value === 1/0) {
return '1/0';
}
if (value === -1/0) {
return '-1/0';
}
return value;
}),
array2 = JSON.parse(json, function (key, value) {
if (value === '0/0') {
return 0/0;
}
if (value === '1/0') {
return Infinity;
}
if (value === '-1/0') {
return -1/0;
}
return value;
});
console.log(json);
console.log(array2);
Output
["-1/0",-1,0,1,2,"0/0",4,5,"1/0"]
[-Infinity, -1, 0, 1, 2, NaN, 4, 5, Infinity]
On jsFiddle
JSON.stringify converting Infinity to null
Like the other answers stated, Infinity
is not part of the values JSON can store as value.
You can reverse the censor method on parsing the JSON:
var c = JSON.parse(b, function (key, value) {
return value === "Infinity" ? Infinity : value;
});
In Angular 2, how do you intercept and parse Infinity / NaN bare-words in JSON responses?
I was able to figure out how to achieve this, and it came down to:
- Modifying the request to return as text instead of json
- Catch the text response and replace the bare word symbols with specific string flags
- Parse the text into an object using
JSON.parse
, providing areviver
function to replace the specific string flags with the javascript version of+/-Infinity
andNaN
Here's the Angular HttpInterceptor
I came up with:
import {Injectable} from '@angular/core';
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
import {Observable} from 'rxjs';
import {map} from 'rxjs/operators';
@Injectable()
export class JsonBareWordNumericSymbolTranslator implements HttpInterceptor {
private static infinityFlag = '__INFINITY_FLAG__';
private static negInfinityFlag = '__NEG_INFINITY_FLAG__';
private static nanFlag = '__NAN_FLAG__';
private static replaceBareWordSymbolsWithFlags(body: string): string {
const infinityBareWordPattern = /(": )Infinity(,?)/;
const negInfinityBareWordPattern = /(": )-Infinity(,?)/;
const nanBareWordPattern = /(": )NaN(,?)/;
return body
.replace(infinityBareWordPattern, `$1"${this.infinityFlag}"$2`)
.replace(negInfinityBareWordPattern, `$1"${this.negInfinityFlag}"$2`)
.replace(nanBareWordPattern, `$1"${this.nanFlag}"$2`);
}
private static translateJsonWithFlags(substitutedBody: string): any {
return JSON.parse(substitutedBody, (key: string, value: string) => {
if (value === this.infinityFlag) {
return Infinity;
} else if (value === this.negInfinityFlag) {
return -Infinity;
} else if (value === this.nanFlag) {
return NaN;
} else {
return value;
}
});
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.responseType !== 'json') {
// Do not modify requests with response types other than json
return next.handle(req);
}
return next.handle(req.clone({responseType: 'text'})).pipe(
map((event) => {
if (!(event instanceof HttpResponse)) {
return event;
}
const substitutedBody = JsonBareWordNumericSymbolTranslator.replaceBareWordSymbolsWithFlags(event.body);
const parsedJson = JsonBareWordNumericSymbolTranslator.translateJsonWithFlags(substitutedBody);
return event.clone({body: parsedJson});
})
);
}
}
Are null and Infinity interchangeable in Javascript?
Here's the same code in a snippet you can run in your browser. As you can see, Infinity
and null
are not equal.
let RANGE_DEFAULT_OPTIONS = { min: 0, max: Infinity };
console.log(RANGE_DEFAULT_OPTIONS);
console.log('strict equality', Infinity === null);
console.log('loose equality', Infinity == null);
Related Topics
Replace All Spaces in a String with '+'
Pagination on a List Using Ng-Repeat
JavaScript Custom Event Listener
Function to Calculate Distance Between Two Coordinates
Get Query String Parameters Url Values with Jquery/JavaScript (Querystring)
How to Trigger a Bootstrap Modal Programmatically
Regex Pattern to Match the End of a String
Capture Click on Div Surrounding an Iframe
Disable Hover Effects on Mobile Browsers
How to Disable Right-Click Context-Menu in JavaScript
Paste an Image from Clipboard Using JavaScript
Node.Js Async/Await Using with MySQL
Understanding JavaScript Scope with "Var That = This"
How to Make 'Setinterval' Behave More in Sync, or How to Use 'Settimeout' Instead