¿Alguna idea de por qué JSON omitió NaN y +/- Infinity? Pone a Javascript en la extraña situación en la que los objetos que de otro modo serían serializables, no lo son, si contienen valores de NaN o +/- infinito.
Parece que esto ha sido moldeado: ver RFC4627 y ECMA-262 (sección 24.5.2, JSON.stringify, NOTA 4, página 683 del PDF de ECMA-262 en la última edición):
Los números finitos se stringifican como llamando
ToString(number)
. NaN e Infinity independientemente del signo se representan como la Cadenanull
.
javascript
json
ecma262
Jason S
fuente
fuente
Respuestas:
Infinity
yNaN
no son palabras clave ni nada especial, son solo propiedades en el objeto global (tal cualundefined
) y, como tal, se pueden cambiar. Es por esa razón que JSON no los incluye en la especificación: en esencia, cualquier cadena JSON verdadera debería tener el mismo resultado en EcmaScript si lo haceeval(jsonString)
o noJSON.parse(jsonString)
.Si se permitiera, alguien podría inyectar un código similar a
en un foro (o lo que sea) y luego cualquier uso de json en ese sitio podría verse comprometido.
fuente
NaN
yInfinity
son nombres de propiedades, por lo tanto, mientras String (1/0) produce una cadena"Infinity"
que es solo la representación de cadena del valor infinito. No es posible representar ya seaNaN
oInfinity
como valores literales es ES - ya sea que usted tiene que utilizar una expresión (por ejemplo, 1/0, 0/0, etc.) O una búsqueda de propiedad (en referencia aInfinity
, oNaN
). Como esos requieren ejecución de código, no pueden incluirse en JSON.Sobre la pregunta original: estoy de acuerdo con el usuario "cbare" en que esta es una omisión desafortunada en JSON. IEEE754 define estos como tres valores especiales de un número de coma flotante. Por lo tanto, JSON no puede representar completamente los números de coma flotante IEEE754. De hecho, es aún peor, ya que JSON como se define en ECMA262 5.1 ni siquiera define si sus números se basan en IEEE754. Dado que el flujo de diseño descrito para la función stringify () en ECMA262 menciona los tres valores IEEE especiales, se puede sospechar que la intención era de hecho admitir números de punto flotante IEEE754.
Como otro punto de datos, no relacionado con la pregunta: tipos de datos XML xs: float y xs: double afirman que están basados en números de punto flotante IEEE754, y que admiten la representación de estos tres valores especiales (Ver W3C XSD 1.0 Parte 2 , Tipos de datos).
fuente
¿Podría adaptar el patrón de objeto nulo y en su JSON representar valores como
Luego, al verificar, puede verificar el tipo
Sé que en Java puedes anular los métodos de serialización para implementar tal cosa. No estoy seguro de dónde está su serialización, por lo que no puedo dar detalles sobre cómo implementarlo en los métodos de serialización.
fuente
undefined
no es una palabra clave, es una propiedad del objeto global"undefined" in this
devuelve verdadero en el ámbito global. También significa que puedes hacerundefined = 42
y seif (myVar == undefined)
convierte (esencialmente)myVar == 42
. Esto se remonta a los primeros días de ecmascript nee javascript, dondeundefined
no existía de forma predeterminada, por lo que las personas simplemente lo hicieronvar undefined
en el ámbito global. En consecuenciaundefined
, no se podría convertir en una palabra clave sin romper los sitios existentes, por lo que estábamos condenados a ser indefinidos una propiedad normal.undefined
es una propiedad global porque se especifica como tal. Consulte 15.1.1.3 de ECMAScript-262 3rd ed.Las cadenas "Infinity", "-Infinity" y "NaN" obligan a los valores esperados en JS. Entonces argumentaría que la forma correcta de representar estos valores en JSON es como cadenas.
Es solo una lástima que JSON.stringify no lo haga por defecto. Pero, hay una manera:
fuente
NaN
yInfinity
agregar como valores de palabras clave comotrue
yfalse
.Number("Infinity")
,Number("-Infinity")
yNumber("NaN")
JSON.parse("{ \"value\" : -1e99999 }")
regresar fácilmente{ value:-Infinity }
en javascript. Solo que no es compatible con el tipo de número personalizado que podría ser más grande que esoSi tiene acceso al código de serialización, puede representar Infinity como 1.0e + 1024. El exponente es demasiado grande para representarlo en un doble y, cuando se deserializa, se representa como Infinito. Funciona en webkit, ¡no estoy seguro acerca de otros analizadores json!
fuente
Infinity
siempre seráInfinity
así que, ¿por qué no apoyar eso?/0
al final de ellos. Es fácilmente analizable, inmediatamente visible e incluso evaluable. Es inexcusable que aún no lo hayan agregado al estándar:{"Not A Number":0/0,"Infinity":1/0,"Negative Infinity":-1/0}
<< ¿Por qué no?alert(eval("\"Not A Number\"") //works
alert(eval("1/0")) //also works, prints 'Infinity'
. Sin excusas.El IEEE Std 754-2008 actual incluye definiciones para dos representaciones diferentes de punto flotante de 64 bits: un tipo decimal de punto flotante de 64 bits y un tipo binario de punto flotante de 64 bits.
Después de redondear la cadena
.99999990000000006
es la misma que.9999999
en la representación binaria IEEE de 64 bits, pero NO es la misma que.9999999
en la representación decimal IEEE de 64 bits. En IEEE de 64 bits, el punto flotante decimal se.99999990000000006
redondea al valor.9999999000000001
que no es el mismo que el.9999999
valor decimal .Dado que JSON solo trata los valores numéricos como cadenas numéricas de dígitos decimales, no hay forma de que un sistema que admita representaciones de punto flotante binario y decimal IEEE (como IBM Power) determine cuál de los dos posibles valores de punto flotante numérico IEEE es destinado a.
fuente
Posible solución para casos como {"key": Infinity}:
La idea general es reemplazar las ocurrencias de valores no válidos con una cadena que reconoceremos al analizar y reemplazarla nuevamente con la representación JavaScript adecuada.
fuente
El motivo se indica en la página ii del Estándar ECMA-404 La sintaxis de intercambio de datos JSON, primera edición
La razón no es, como muchos han afirmado, debido a las representaciones de
NaN
yInfinity
la escritura ECMA. La simplicidad es un principio de diseño central de JSON.fuente
Si, como yo, no tiene control sobre el código de serialización, puede lidiar con los valores de NaN reemplazándolos por nulos o cualquier otro valor como un truco de la siguiente manera:
En esencia, se llamará a .fail cuando el analizador json original detecte un token no válido. Luego se usa un reemplazo de cadena para reemplazar los tokens no válidos. En mi caso, es una excepción que el serializador devuelva valores de NaN, por lo que este método es el mejor enfoque. Si los resultados normalmente contienen un token no válido, sería mejor no usar $ .get, sino recuperar manualmente el resultado JSON y ejecutar siempre el reemplazo de la cadena.
fuente
{ "tune": "NaNaNaNaNaNaNaNa BATMAN", "score": NaN }