Masz pojęcie, dlaczego JSON pomijał NaN i +/- Infinity? Stawia JavaScript w dziwnej sytuacji, w której obiekty, które w innym przypadku byłyby możliwe do serializacji, nie są, jeśli zawierają wartości NaN lub +/- nieskończoności.
Wygląda na to, że zostało to odlane w kamieniu: patrz RFC4627 i ECMA-262 (sekcja 24.5.2, JSON.stringify, UWAGA 4, strona 683 ECMA-262 pdf w ostatniej edycji):
Liczby skończone są taktowane jak przez wywołanie
ToString(number)
. NaN i Infinity niezależnie od znaku są reprezentowane jako ciągnull
.
javascript
json
ecma262
Jason S.
źródło
źródło
Odpowiedzi:
Infinity
iNaN
nie są słowami kluczowymi ani niczym specjalnym, są tylko właściwościami obiektu globalnego (jak jestundefined
) i jako takie można je zmienić. Z tego powodu JSON nie włącza ich do specyfikacji - w zasadzie każdy prawdziwy ciąg JSON powinien mieć taki sam wynik w EcmaScript, jeśli to zrobiszeval(jsonString)
lubJSON.parse(jsonString)
.Gdyby było dozwolone, ktoś mógłby wstrzyknąć kod podobny do
na forum (lub cokolwiek innego), a następnie jakiekolwiek użycie JSON w tej witrynie może być zagrożone.
źródło
NaN
iInfinity
są nazwami własności, więc podczas gdy String (1/0) tworzy ciąg,"Infinity"
który jest po prostu ciągiem reprezentującym wartość nieskończoności. Nie jest możliwe, aby reprezentować alboNaN
czyInfinity
jako dosłowne wartości jest ES - albo trzeba użyć wyrażenia (np 1/0, 0/0 itd.) Lub odnośnika własności (w odniesieniu doInfinity
alboNaN
). Ponieważ wymagają one wykonania kodu, nie można ich włączyć do JSON.Na pierwotne pytanie: zgadzam się z użytkownikiem „cbare”, ponieważ jest to niefortunne pominięcie w JSON. IEEE754 definiuje je jako trzy specjalne wartości liczby zmiennoprzecinkowej. Zatem JSON nie może w pełni reprezentować liczb zmiennoprzecinkowych IEEE754. W rzeczywistości jest jeszcze gorzej, ponieważ JSON zdefiniowany w ECMA262 5.1 nawet nie określa, czy jego liczby są oparte na IEEE754. Ponieważ przepływ projektowania opisany dla funkcji stringify () w ECMA262 wspomina o trzech specjalnych wartościach IEEE, można podejrzewać, że w rzeczywistości chodziło o obsługę liczb zmiennoprzecinkowych IEEE754.
Jako jeden inny punkt danych niezwiązany z pytaniem: typy danych XML xs: float i xs: double informują, że są oparte na liczbach zmiennoprzecinkowych IEEE754 i obsługują reprezentację tych trzech wartości specjalnych (patrz W3C XSD 1.0 część 2 , Typy danych).
źródło
Czy możesz dostosować wzorzec obiektu zerowego, aw swoim JSON reprezentować takie wartości jak
Następnie podczas sprawdzania możesz sprawdzić typ
Wiem, że w Javie możesz zastąpić metody serializacji, aby zaimplementować coś takiego. Nie jestem pewien, skąd twoja serializacja, więc nie mogę podać szczegółów, jak zaimplementować ją w metodach serializacji.
źródło
undefined
nie jest słowem kluczowym, jest własnością obiektu globalnego"undefined" in this
zwraca wartość true w zakresie globalnym. Oznacza to również, że możesz to zrobićundefined = 42
iif (myVar == undefined)
staje się (zasadniczo)myVar == 42
. To nawiązuje do początków evascript nee javascript, w którychundefined
domyślnie nie istniały, więc ludzie po prostu działalivar undefined
w zakresie globalnym. W związku z tymundefined
nie można uczynić słowa kluczowego bez zerwania z istniejącymi witrynami, dlatego byliśmy skazani na wieczny niezdecydowanie, że jest to normalna właściwość.undefined
jest własnością globalną, ponieważ jest określona jako taka. Zobacz 15.1.1.3 ECMAScript-262 wydanie 3.Ciągi „Infinity”, „-Infinity” i „NaN” wszystkie wymuszają oczekiwane wartości w JS. Więc argumentowałbym, że właściwym sposobem reprezentowania tych wartości w JSON są ciągi znaków.
Szkoda tylko, że JSON.stringify nie robi tego domyślnie. Ale jest sposób:
źródło
NaN
iInfinity
dodaliśmy jako wartości słów kluczowych takich jaktrue
ifalse
.Number("Infinity")
,Number("-Infinity")
iNumber("NaN")
JSON.parse("{ \"value\" : -1e99999 }")
łatwo wrócić{ value:-Infinity }
w javascript. Tylko to po prostu nie jest kompatybilne z niestandardowym typem numeru, który może być większyJeśli masz dostęp do kodu serializacji, możesz reprezentować Infinity jako 1.0e + 1024. Wykładnik jest zbyt duży, aby reprezentować go podwójnie, a po deserializacji jest reprezentowany jako Nieskończoność. Działa na zestawie internetowym, niepewny co do innych parserów json!
źródło
Infinity
zawsze będzieInfinity
, więc dlaczego nie wesprzeć tego?/0
je na końcu. Jest łatwo analizowalny, natychmiast widoczny, a nawet oceniany. Jest niewybaczalne, że nie dodali go jeszcze do standardu:{"Not A Number":0/0,"Infinity":1/0,"Negative Infinity":-1/0}
<< Dlaczego nie?alert(eval("\"Not A Number\"") //works
alert(eval("1/0")) //also works, prints 'Infinity'
. Bez wymówek.Obecny standard IEEE 754-2008 zawiera definicje dwóch różnych 64-bitowych reprezentacji zmiennoprzecinkowych: dziesiętnego 64-bitowego typu zmiennoprzecinkowego i binarnego 64-bitowego typu zmiennoprzecinkowego.
Po zaokrągleniu ciąg znaków
.99999990000000006
jest taki sam jak.9999999
w binarnej reprezentacji 64-bitowej IEEE, ale NIE jest taki sam jak.9999999
w reprezentacji dziesiętnej 64-bitowej IEEE. W 64-bitowym.99999990000000006
zaokrągleniu dziesiętnym zmiennoprzecinkowym IEEE do wartości,.9999999000000001
która nie jest taka sama jak.9999999
wartość dziesiętna .Ponieważ JSON po prostu traktuje wartości liczbowe jako ciągi liczb dziesiętnych, system nie obsługuje zarówno binarnych, jak i dziesiętnych reprezentacji zmiennoprzecinkowych IEEE (takich jak IBM Power), aby określić, która z dwóch możliwych wartości liczbowych zmiennoprzecinkowych IEEE jest zamierzony.
źródło
Potencjalne obejście takich przypadków jak {„key”: Infinity}:
Ogólną ideą jest zastąpienie wystąpień niepoprawnych wartości ciągiem, który rozpoznamy podczas analizy i zastąpienie go odpowiednią reprezentacją JavaScript.
źródło
Przyczynę podano na stronie ii w Standardowej ECMA-404 Składnia wymiany danych JSON, wydanie pierwsze
Przyczyna nie jest, jak wielu twierdziło, ze względu na reprezentację
NaN
iInfinity
skrypt ECMA. Prostota jest podstawową zasadą projektowania JSON.źródło
Jeśli, podobnie jak ja, nie masz kontroli nad kodem serializacji, możesz poradzić sobie z wartościami NaN, zastępując je wartościami null lub dowolnymi innymi wartościami w ramach hackowania w następujący sposób:
Zasadniczo .fail zostanie wywołany, gdy oryginalny parser json wykryje nieprawidłowy token. Następnie zastąpiono ciąg znaków, aby zastąpić nieprawidłowe tokeny. W moim przypadku serializator jest wyjątkiem, aby zwracać wartości NaN, więc ta metoda jest najlepszym podejściem. Jeśli wyniki zwykle zawierają nieprawidłowy token, lepiej byłoby nie używać $ .get, ale zamiast tego ręcznie pobrać wynik JSON i zawsze uruchamiać zamianę łańcucha.
źródło
{ "tune": "NaNaNaNaNaNaNaNa BATMAN", "score": NaN }