209 votes

JSON n'a pas tenu compte de l'infini et de NaN ; statut de JSON dans ECMAScript ?

Une idée de la raison pour laquelle JSON a laissé de côté NaN et +/- Infini ? Cela place Javascript dans une situation étrange où des objets qui seraient autrement sérialisables, ne le sont pas, s'ils contiennent des valeurs NaN ou +/- infini.

Il semble que cela ait été coulé dans le béton : voir RFC4627 y ECMA-262 (section 24.5.2, JSON.stringify, NOTE 4, page 683 du pdf ECMA-262 lors de la dernière édition) :

Les nombres finis sont stringifiés comme si en appelant ToString(number) . NaN et Infini, quel que soit le signe, sont représentés par la chaîne de caractères null .

0 votes

Je ne trouve pas cette citation dans les deux documents.

1 votes

Je l'ai corrigé, il semble qu'il y avait une référence périmée / édition périmée en quelque sorte.

105voto

olliej Points 16255

Infinity y NaN ne sont pas des mots-clés ou quoi que ce soit de spécial, ce sont juste des propriétés de l'objet global (comme l'est undefined ) et, en tant que tel, peut être modifié. C'est pour cette raison que JSON ne les inclut pas dans la spécification -- en substance, toute chaîne JSON véritable devrait avoir le même résultat dans EcmaScript si vous faites eval(jsonString) o JSON.parse(jsonString) .

Si cela était autorisé, quelqu'un pourrait injecter du code semblable à

NaN={valueOf:function(){ do evil }};
Infinity={valueOf:function(){ do evil }};

dans un forum (ou autre) et ensuite toute utilisation de json sur ce site pourrait être compromise.

0 votes

Où est-il dit que Infini et NaN sont des mots-clés ? Ce sont des valeurs doubles Javascript.

34 votes

Si vous évaluez 1/0 vous obtenez l'infini, si vous évaluez -1/0 vous obtenez -Infini, si vous évaluez 0/0 vous obtenez NaN.

9 votes

Mais les termes NaN y Infinity sont des noms de propriétés, donc alors que String(1/0) produit une chaîne de caractères "Infinity" qui est juste la représentation en chaîne de la valeur infini. Il n'est pas possible de représenter NaN o Infinity en tant que valeurs littérales est ES -- vous devez soit utiliser une expression (par exemple 1/0, 0/0 etc) ou une recherche de propriété (se référant à Infinity o NaN ). Comme ils nécessitent l'exécution d'un code, ils ne peuvent pas être inclus dans JSON.

62voto

Andreas Maier Points 151

Sur la question originale : Je suis d'accord avec l'utilisateur "cbare" pour dire que c'est une omission malheureuse dans JSON. L'IEEE754 les définit comme trois valeurs spéciales d'un nombre à virgule flottante. JSON ne peut donc pas représenter entièrement les nombres à virgule flottante IEEE754. En fait, c'est même pire, puisque le JSON tel que défini dans la norme ECMA262 5.1 ne définit même pas si ses nombres sont basés sur l'IEEE754. Étant donné que le flux de conception décrit pour la fonction stringify() de la norme ECMA262 mentionne les trois valeurs spéciales IEEE, on peut soupçonner que l'intention était en fait de prendre en charge les nombres à virgule flottante IEEE754.

Comme autre point de données, sans rapport avec la question : Les types de données XML xs:float et xs:double indiquent qu'ils sont basés sur les nombres à virgule flottante IEEE754 et prennent en charge la représentation de ces trois valeurs spéciales (voir W3C XSD 1.0 Part 2, Datatypes).

5 votes

Je suis d'accord que tout cela est malheureux. Mais c'est peut-être une bonne chose que les nombres JSON ne spécifient pas le format exact de la virgule flottante. Même la norme IEEE754 spécifie de nombreux formats - différentes tailles, et une distinction entre les exposants décimaux et binaires. JSON est particulièrement bien adapté au décimal, il serait donc dommage qu'une norme l'épingle au binaire.

6 votes

@AdrianRatnapala +1 En effet : Les nombres JSON ont une précision potentiellement infinie, ils sont donc bien meilleurs que les spécifications IEEE, car ils n'ont pas de limite de taille, pas de limite de précision et pas d'effet d'arrondi (si le sérialiseur peut le gérer).

5 votes

@ArnaudBouchez. Cela dit, JSON devrait quand même supporter les chaînes représentant NaN et +-Infini. Même si JSON ne devrait pas être épinglé à un format IEEE, les personnes définissant le format des nombres devraient au moins regarder la page IEEE754 de wikipedia et s'arrêter un moment pour réfléchir.

20voto

Zoidberg Points 5656

Pourriez-vous adapter le modèle d'objet nul, et représenter dans votre JSON des valeurs telles que

"myNum" : {
   "isNaN" :false,
   "isInfinity" :true
}

Ensuite, lors de la vérification, vous pouvez rechercher le type

if (typeof(myObj.myNum) == 'number') {/* do this */}
else if (myObj.myNum.isNaN) {/* do that*/}
else if (myObj.myNum.isInfinity) {/* Do another thing */}

Je sais qu'en Java, vous pouvez surcharger les méthodes de sérialisation afin d'implémenter une telle chose. Je ne sais pas d'où vient votre sérialisation, donc je ne peux pas donner de détails sur la façon de l'implémenter dans les méthodes de sérialisation.

1 votes

Hmmm... c'est une réponse à une solution de contournement ; je ne demandais pas vraiment une solution de contournement mais plutôt pourquoi ces valeurs étaient exclues. Mais +1 quand même.

0 votes

Quant au pourquoi, je ne vois pas pourquoi ils les auraient laissés de côté. Peut-être s'attendent-ils à ce que vous utilisiez les valeurs maximales et minimales pour un nombre particulier, comme Integer.MAX_VALUE. Jusqu'à I.E. 5.5, il n'y avait même pas de mot-clé null en javascript (au moins pour IE qui est nul), vous ne pouviez même pas utiliser le mot-clé undefined, ce qui rendait javascript beaucoup plus difficile. C'est peut-être la même chose, peut-être que les navigateurs adopteront plus cela dans le futur.

2 votes

@Zoidberg : undefined n'est pas un mot clé, c'est une propriété de l'objet global

7voto

Ates Goral Points 47670

Serait-ce parce que JSON est destiné à être un format d'échange de données qui peut être utilisé dans une variété de plates-formes et autoriser NaN/Infini le rendrait moins portable ?

7voto

kuwerty Points 132

Si vous avez accès au code de sérialisation, vous pouvez représenter l'infini par 1,0e+1024. L'exposant est trop grand pour être représenté dans un double et lorsqu'il est désérialisé, il est représenté comme Infini. Fonctionne sur webkit, pas sûr pour les autres parsers json !

5 votes

IEEE754 supporte les nombres à virgule flottante de 128 bits, donc 1.0e5000 est mieux.

4 votes

Ton : 128 bits ont été ajoutés plus tard. Que se passe-t-il s'ils décident d'ajouter 256 bits ? Il faudra alors ajouter plus de zéros, et le code existant se comportera différemment. Infinity sera toujours Infinity alors pourquoi ne pas le soutenir ?

1 votes

Une idée géniale ! J'étais sur le point de passer à un format différent ou d'ajouter un code de contournement encombrant à mon analyseur. Ce n'est pas idéal pour tous les cas, mais dans mon cas, où l'infini n'est qu'un cas limite optimisé d'une séquence convergente, c'est tout simplement parfait et même si une plus grande précision était introduite, ce serait toujours correct. Merci !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X