Alguma idéia de por que o JSON deixou de fora o NaN e o +/- Infinity? Ele coloca o Javascript na estranha situação em que os objetos que seriam serializáveis não são, se eles contêm NaN ou +/- valores infinitos.
Parece que isso foi feito em pedra: consulte RFC4627 e ECMA-262 (seção 24.5.2, JSON.stringify, NOTA 4, página 683 do ECMA-262 em última edição):
Os números finitos são especificados como se fossem chamados
ToString(number)
. NaN e Infinity, independentemente do sinal, são representados como a Stringnull
.
javascript
json
ecma262
Jason S
fonte
fonte
Respostas:
Infinity
eNaN
não são palavras-chave ou nada de especial, são apenas propriedades no objeto global (como estãoundefined
) e, como tal, podem ser alteradas. É por esse motivo que o JSON não os inclui na especificação - em essência, qualquer string JSON verdadeira deve ter o mesmo resultado no EcmaScript se você tivereval(jsonString)
ouJSON.parse(jsonString)
.Se fosse permitido, alguém poderia injetar código semelhante ao
em um fórum (ou o que seja) e, em seguida, qualquer uso de json nesse site poderá ser comprometido.
fonte
NaN
eInfinity
são nomes de propriedades, portanto, enquanto String (1/0) produz uma string"Infinity"
que é apenas a representação da string do valor infinito. Não é possível representar umNaN
ouInfinity
como os valores literais são ES - você precisa usar uma expressão (por exemplo, 1/0, 0/0 etc) ou uma pesquisa de propriedade (consultandoInfinity
ouNaN
). Como esses requerem execução de código, eles não podem ser incluídos no JSON.Sobre a questão original: concordo com o usuário "cbare", pois é uma omissão infeliz no JSON. IEEE754 define esses três valores especiais de um número de ponto flutuante. Portanto, o JSON não pode representar totalmente os números de ponto flutuante IEEE754. Na verdade, é ainda pior, pois o JSON, conforme definido no ECMA262 5.1, nem mesmo define se seus números são baseados no IEEE754. Como o fluxo de projeto descrito para a função stringify () no ECMA262 menciona os três valores IEEE especiais, pode-se suspeitar que a intenção era de fato suportar números de ponto flutuante IEEE754.
Como outro ponto de dados, não relacionado à pergunta: tipos de dados XML xs: float e xs: double afirmam que são baseados nos números de ponto flutuante IEEE754 e suportam a representação desses três valores especiais (consulte W3C XSD 1.0 Parte 2 , Tipos de dados).
fonte
Você poderia adaptar o padrão de objeto nulo e, em seu JSON, representar valores como
Então, ao verificar, você pode verificar o tipo
Eu sei que em Java você pode substituir os métodos de serialização para implementar uma coisa dessas. Não sei de onde você está serializando, então não posso fornecer detalhes sobre como implementá-lo nos métodos de serialização.
fonte
undefined
não é uma palavra-chave, é uma propriedade do objeto global"undefined" in this
retorna verdadeira no escopo global. Isso também significa que você pode fazerundefined = 42
eif (myVar == undefined)
se tornar (essencialmente)myVar == 42
. Isso remonta aos primeiros dias do ecmascript nee javascript, ondeundefined
não existia por padrão, então as pessoas simplesmente existiamvar undefined
no escopo global. Consequentemente,undefined
não era possível criar uma palavra-chave sem quebrar os sites existentes e, por isso, estávamos condenados a não ser definidos como uma propriedade normal.undefined
é uma propriedade global porque é especificada como tal. Consulte 15.1.1.3 do ECMAScript-262 3rd ed.As cadeias "Infinity", "-Infinity" e "NaN" são coerentes com os valores esperados em JS. Então, eu argumentaria que a maneira correta de representar esses valores no JSON é como strings.
É uma pena que o JSON.stringify não faça isso por padrão. Mas, existe um jeito:
fonte
NaN
eInfinity
adicionamos como valores de palavras-chave comotrue
efalse
, no entanto.Number("Infinity")
,Number("-Infinity")
eNumber("NaN")
JSON.parse("{ \"value\" : -1e99999 }")
retornar facilmente{ value:-Infinity }
em javascript. Só que não é compatível com o tipo de número personalizado que pode ser maior que issoSe você tiver acesso ao código de serialização, poderá representar o Infinito como 1.0e + 1024. O expoente é muito grande para representar em dobro e, quando desserializado, é representado como Infinito. Funciona no webkit, inseguro sobre outros analisadores de json!
fonte
Infinity
sempre seráInfinity
, então por que não apoiar isso?/0
ao final deles. É facilmente analisável, imediatamente visível e até avaliável. É indesculpável que eles ainda não o tenham adicionado ao padrão:{"Not A Number":0/0,"Infinity":1/0,"Negative Infinity":-1/0}
<< Por que não?alert(eval("\"Not A Number\"") //works
alert(eval("1/0")) //also works, prints 'Infinity'
. Sem desculpa.O atual IEEE Std 754-2008 inclui definições para duas representações de ponto flutuante de 64 bits diferentes: um tipo de ponto flutuante decimal de 64 bits e um tipo de ponto flutuante binário de 64 bits.
Após o arredondamento, a sequência
.99999990000000006
é a mesma que.9999999
na representação binária de 64 bits do IEEE, mas NÃO é a mesma que.9999999
na representação decimal de 64 bits do IEEE. No ponto IEEE decimal de 64 bits, o ponto flutuante.99999990000000006
arredonda para o valor.9999999000000001
que não é igual ao.9999999
valor decimal .Como o JSON trata apenas valores numéricos como sequências numéricas de dígitos decimais, não há como um sistema que suporte representações de ponto flutuante decimal e binário IEEE (como IBM Power) determinar qual dos dois possíveis valores numéricos de ponto flutuante IEEE é pretendido.
fonte
Solução alternativa em potencial para casos como {"key": Infinity}:
A idéia geral é substituir ocorrências de valores inválidos por uma sequência que reconheceremos ao analisar e substituí-la novamente pela representação JavaScript apropriada.
fonte
O motivo está indicado na página ii no Padrão ECMA-404 A Sintaxe de Intercâmbio de Dados JSON, 1ª Edição
O motivo não é, como muitos afirmaram, devido às representações
NaN
e aoInfinity
script ECMA. A simplicidade é um princípio básico de design do JSON.fonte
Se, como eu, você não tiver controle sobre o código de serialização, poderá lidar com os valores de NaN, substituindo-os por nulos ou qualquer outro valor como um hack, como segue:
Em essência, .fail será chamado quando o analisador json original detectar um token inválido. Em seguida, uma sequência de substituição é usada para substituir os tokens inválidos. No meu caso, é uma exceção o serializador retornar valores NaN, portanto esse método é a melhor abordagem. Se os resultados normalmente contiverem token inválido, é melhor não usar $ .get, mas recuperar manualmente o resultado JSON e sempre executar a substituição da cadeia.
fonte
{ "tune": "NaNaNaNaNaNaNaNa BATMAN", "score": NaN }