Come analizzare la stringa JSON contenente “NaN” in Node.js

Avere un’app node.js che sta ricevendo stringhe di dati JSON che contengono il NaN letterale, come

"[1, 2, 3, NaN, 5, 6]" 

JSON.parse(...) in Node.js. Mi piacerebbe analizzarlo, se posso farlo su un object.

So che NaN non fa parte delle specifiche JSON. La maggior parte dei link SO ( inviando NaN in json ) suggeriscono di correggere l’output.

Qui, sebbene i dati siano prodotti in un server che non controllo, è da una libreria Java commerciale dove posso vedere il codice sorgente. Ed è prodotto dalla libreria Gson di Google:

 private Gson gson = (new GsonBuilder().serializeSpecialFloatingPointValues().create()); ... gson.toJson(data[i], Vector.class, jsonOut) 

Quindi sembra una fonte legittima. E secondo l’ API Gson Javadoc dice che dovrei essere in grado di analizzarlo:

La sezione 2.4 della specifica JSON non consente i doppi valori speciali (NaN, Infinity, -Infinity). Tuttavia, le specifiche di Javascript (vedere la sezione 4.3.20, 4.3.22, 4.3.23) consentono questi valori come valori Javascript validi. Inoltre, la maggior parte dei motori JavaScript accetta questi valori speciali in JSON senza problemi. Quindi, a livello pratico, ha senso accettare questi valori come JSON validi anche se le specifiche JSON non li autorizzano.

Nonostante ciò, questo non funziona sia in Node.js sia in Chrome: JSON.parse('[1,2,3,NaN,"5"]')

C’è un flag da impostare in JSON.parse ()? O un parser alternativo che accetta NaN come un letterale?

Sono stato su Google per un po ‘, ma non riesco a trovare un documento su questo problema.

PHP: come codificare numeri infinito o NaN in JSON?

Avere un’app node.js che sta ricevendo stringhe di dati JSON che contengono il NaN letterale, come

Quindi l’app NodeJS non sta ricevendo JSON , sta ricevendo del testo vagamente simile a JSON. NaN non è un token JSON valido.

Tre opzioni:

1. Ottenere il codice sorgente per produrre correttamente JSON

Questo è ovviamente il corso preferito. I dati non sono JSON, che dovrebbero essere corretti, il che risolverebbe il tuo problema.

2. Tollerare il NaN in modo semplice:

Potresti sostituirlo con null prima di analizzarlo, ad esempio:

 var result = JSON.parse(yourString.replace(/\bNaN\b/g, "null")); 

… e quindi gestisci null s nel risultato. Ma è molto semplice, non consente la possibilità che i personaggi NaN possano apparire in una stringa da qualche parte.

Alternativamente, ruotando l’idea del reviver Matt Ball (ora cancellata) , potresti cambiarla in una stringa speciale (come "***NaN***" ) e quindi usare un reviver per sostituirlo con il vero NaN :

 var result = JSON.parse(yourString.replace(/\bNaN\b/g, '"***NaN***"'), function(key, value) { return value === "***NaN***" ? NaN : value; }); 

… ma questo ha lo stesso problema di essere un po ‘semplice, supponendo che i personaggi NaN non appaiano mai in un posto appropriato.

3. Utilizzare (rabbrividire!) eval

Se si conosce e si fida della fonte di questi dati e NON c’è possibilità che vengano manomessi durante il transito , è ansible utilizzare eval per analizzarli invece di JSON.parse . Poiché eval consente la piena syntax JavaScript, incluso NaN , funziona. Spero di aver reso l’avvertimento abbastanza audace da far capire alla gente che lo raccomanderei solo in una percentuale molto, molto, molto piccola di situazioni. Ma ancora, ricorda che eval permette l’esecuzione arbitraria del codice, quindi se c’è qualche possibilità che la stringa sia stata manomessa, non usarla.

Quando si tratta di qualcosa di matematico o di dati di settore, NaN è terribilmente conveniente (e spesso anche gli infiniti). Ed è uno standard del settore dal momento che IEEE754.

Questo è ovviamente il motivo per cui alcune librerie, in particolare GSON, consentono di includerle nel JSON che producono, perdendo purezza standard e guadagnando sanità mentale.

Le soluzioni Revival e regex non sono utilizzabili in modo affidabile in un progetto reale quando si scambiano oggetti dinamici complessi.

E eval ha anche problemi, uno dei quali è il fatto che è sobject a crash su IE quando la stringa JSON è grande, un altro è rischi per la sicurezza.

Ecco perché ho scritto un parser specifico (utilizzato in produzione): JSON.parseMore

La soluzione corretta è ricompilare il parser e contribuire con un flag booleano “allowNan” alla base di origine. Questa è la soluzione che hanno altre librerie (viene in mente python).

Le buone librerie JSON analizzeranno in modo permissivo tutto ciò che assomiglia vagamente a JSON con i giusti flag set (JSON.pm di perl è notevolmente flessibile) … ma quando scrivono un messaggio producono JSON standard.

IE: lascia la stanza più pulita di quanto tu non abbia trovato.