Jaki jest minimalny prawidłowy kod JSON?


174

Uważnie przeczytałem opis JSON http://json.org/, ale nie jestem pewien, czy znam odpowiedź na proste pytanie. Jakie ciągi są najmniejszym możliwym prawidłowym kodem JSON?

  • "string" czy ciąg to prawidłowy format JSON?
  • 42 czy prosta liczba jest poprawna w formacie JSON?
  • true czy wartość logiczna to prawidłowy format JSON?
  • {} czy pusty obiekt jest prawidłowym plikiem JSON?
  • [] czy pusta tablica to prawidłowy format JSON?

12
Testy na jsonlint.com , ostatnie dwa są ważne, inne nie.
ironcito,

1
niektóre parsery JSON oczekują tablicy lub obiektu. Narzekają tylko na liczbę lub ciąg.
akonsu

3
Na razie są one ważne
Brian Colavito


krótka odpowiedź - {}
Tukaram Bhosale

Odpowiedzi:


156

W chwili pisania tego tekstu JSON był opisany wyłącznie w RFC4627 . Opisuje (na początku „2”) tekst JSON jako zserializowany obiekt lub tablicę.

Oznacza to, że tylko {} i []są prawidłowe, pełne ciągi JSON w parserach i ciągnikach zgodnych z tym standardem.

Jednak wprowadzenie ECMA-404 to zmienia, a zaktualizowane porady można przeczytać tutaj . Napisałem również wpis na blogu w tej sprawie.


Aby jeszcze bardziej zmylić sprawę, JSONobiekt (np. JSON.parse()I JSON.stringify()) dostępny w przeglądarkach internetowych jest ustandaryzowany w ES5 i jasno definiuje dopuszczalne teksty JSON, takie jak:

Format wymiany JSON używany w tej specyfikacji jest dokładnie taki sam, jak opisany w dokumencie RFC 4627 z dwoma wyjątkami:

  • Produkcja JSONText najwyższego poziomu gramatyki JSON ECMAScript może składać się z dowolnej wartości JSONValue, a nie być ograniczona do obiektu JSONObject lub JSONArray, jak określono w RFC 4627.

  • ścięte

Oznaczałoby to, że wszystkie wartości JSON (w tym ciągi, wartości null i liczby) są akceptowane przez obiekt JSON, nawet jeśli obiekt JSON jest technicznie zgodny z RFC 4627.

Zauważ, że możesz zatem określić liczbę w zgodnej przeglądarce za pośrednictwem JSON.stringify(5), która zostanie odrzucona przez inny parser, który jest zgodny z RFC4627, ale który nie ma określonego wyjątku wymienionego powyżej. Na przykład Ruby wydaje się być jednym z takich przykładów, w którym jako root przyjmuje tylko obiekty i tablice . Z drugiej strony PHP specjalnie dodaje wyjątek, że „będzie również kodować i dekodować typy skalarne i NULL”.


@amdorra: Czy możesz być bardziej szczegółowy, gdzie to widzisz?
Matt,

5
JSON nie jest rzeczownikiem, więc „a JSON” jest bez znaczenia. Każda „wartość JSON” jest „wartością JSON”, ale parsery często oczekują „tekstu JSON” zgodnie z definicją w tym dokumencie RFC.
IMSoP

2
mój zły, wtedy usunę moją odpowiedź
amdorra

1
@jmoreno Czy mógłbyś wyjaśnić swój komentarz? Czy mówisztrue , falsealbo nullsam jest ważny tekst JSON? Czy mógłbyś zacytować źródło, ponieważ jest to sprzeczne z większością innych odpowiedzi / komentarzy tutaj?
Lawrence Johnston,

2
@jmoreno: Z pewnością cytat z sekcji 2 „Tekst JSON jest zserializowanym obiektem lub tablicą”. Się temu sprzeciwia? JSON Lint również uważa, że ​​nie-tablica lub obiekt jest prawidłowy. Nie ma debaty na temat tego, czy ciąg jest prawidłowym literałem JSON; to jest kwestia tego, czy łańcuch sam w sobie jest prawidłowy.
Matt

42

W Internecie istnieją co najmniej cztery dokumenty, które można uznać za standardy JSON. Wszystkie odnośniki RFC opisują typ MIME application/json. Oto, co każdy ma do powiedzenia na temat wartości najwyższego poziomu i czy na górze jest dozwolone cokolwiek innego niż obiekt lub tablica:

RFC-4627 : Nie.

Tekst JSON to sekwencja tokenów. Zestaw tokenów zawiera sześć znaków strukturalnych, ciągi, liczby i trzy nazwy literałów.

Tekst JSON to serializowany obiekt lub tablica.

JSON-text = obiekt / tablica

Zwróć uwagę, że RFC-4627 został oznaczony jako „informacyjny” w przeciwieństwie do „proponowanego standardu” i jest przestarzały przez RFC-7159 , który z kolei został zastąpiony przez RFC-8259.

RFC-8259 : Tak.

Tekst JSON to sekwencja tokenów. Zestaw tokenów zawiera sześć znaków strukturalnych, ciągi, liczby i trzy nazwy literałów.

Tekst JSON to zserializowana wartość. Zwróć uwagę, że niektóre wcześniejsze specyfikacje formatu JSON ograniczały tekst JSON do bycia obiektem lub tablicą. Implementacje, które generują tylko obiekty lub tablice, w których wywoływany jest tekst JSON, będą interoperacyjne w tym sensie, że wszystkie implementacje zaakceptują je jako zgodne teksty JSON.

JSON-text = wartość ws ws

RFC-8259 pochodzi z grudnia 2017 r. I jest oznaczony jako „INTERNET STANDARD”.

ECMA-262 : Tak.

Gramatyka syntaktyczna JSON definiuje prawidłowy tekst JSON pod względem tokenów zdefiniowanych przez gramatykę leksykalną JSON. Symbolem celu w gramatyce jest JSONText.

Składnia JSONText:

JSONValue

JSONValue:

JSONNullLiteral

JSONBooleanLiteral

JSONObject

JSONArray

JSONString

JSONNumber

ECMA-404 : Tak.

Tekst JSON to sekwencja tokenów utworzona z punktów kodowych Unicode, która jest zgodna z gramatyką wartości JSON. Zestaw tokenów zawiera sześć żetonów strukturalnych, ciągi znaków, liczby i trzy żetony nazw literalnych.


10

Zgodnie ze starą definicją w RFC 4627 (która została przestarzała w marcu 2014 r. Przez RFC 7159), wszystkie były poprawnymi „wartościami JSON”, ale tylko dwie ostatnie stanowiłyby pełny „tekst JSON”:

Tekst JSON to serializowany obiekt lub tablica.

W zależności od używanego parsera, samotne „wartości JSON” mogą i tak zostać zaakceptowane. Na przykład (trzymanie się terminologii „wartość JSON” i „tekst JSON”):

  • the JSON.parse()funkcja teraz standaryzowane w nowoczesnych przeglądarek akceptuje żadnych „wartość” JSON
  • funkcja PHP json_decodezostała wprowadzona w wersji 5.2.0, akceptując tylko cały „tekst JSON”, ale została zmieniona tak, aby akceptowała każdą „wartość JSON” w wersji 5.2.1
  • Python json.loadsakceptuje każdą „wartość JSON” zgodnie z przykładami na tej stronie podręcznika
  • walidator pod adresem http://jsonlint.com oczekuje pełnego „tekstu JSON”
  • moduł Ruby JSON akceptuje tylko pełny "tekst JSON" (przynajmniej zgodnie z komentarzami na tej stronie podręcznika )

Rozróżnienie jest trochę podobne do rozróżnienia między „dokumentem XML” a „fragmentem XML”, chociaż technicznie <foo />jest to dobrze sformułowany dokument XML (lepiej byłoby napisać <?xml version="1.0" ?><foo />, ale jak wskazano w komentarzach, <?xmldeklaracja jest technicznie opcjonalna ).


Porównanie XML może być nieodpowiednie, ponieważ dokument XML jest całkowicie prawidłowy bez opcjonalnej deklaracji XML. Zobacz rekomendację XML na w3.org/TR/xml/#sec-well-formed
Gunther

@ Gunther Ach, tak, zapomniałem, że jest to technicznie opcjonalne, chociaż bardzo zalecane.
IMSoP

@Gunther: chwytak: <foo />to dobrze sformułowany dokument XML, ale nie jest prawidłowy . (Ale to samo dotyczy <?xml version="1.0" ?><foo />.)
ruakh

@ruakh Co ciekawe, ta definicja sugeruje, że XML może być „prawidłowy” tylko w stosunku do DTD, co oznacza, że ​​jest tak niewiele dokumentów XML, ponieważ DTD są bardzo rzadko pisane i deklarowane w praktyce (w porównaniu z formatami definicji schematu, takimi jak XSD lub RelaxNG) . Sprawdzałem, bo gdybyś mógł być ważny w odniesieniu do zewnętrznego schematu, bez odwoływania się do niego, to <foo /> może, ale nie musi, być ważny w odniesieniu do określonego schematu , ale nie to stwierdza ten standard.
IMSoP

4

Specyfikacja ecma może być przydatna w celach informacyjnych:

http://www.ecma-international.org/ecma-262/5.1/

Funkcja parsowania analizuje tekst JSON (ciąg w formacie JSON) i tworzy wartość ECMAScript. Format JSON jest ograniczoną formą literału ECMAScript. Obiekty JSON są realizowane jako obiekty ECMAScript. Tablice JSON są realizowane jako tablice ECMAScript. Ciągi JSON, liczby, wartości logiczne i wartości null są realizowane jako ciągi znaków ECMAScript, liczby, wartości logiczne i null. JSON używa bardziej ograniczonego zestawu znaków odstępu niż WhiteSpace i pozwala punktom kodowym Unicode U + 2028 i U + 2029 bezpośrednio pojawiać się w literałach JSONString bez użycia sekwencji ucieczki. Proces analizowania jest podobny do 11.1.4 i 11.1.5 i jest ograniczony gramatyką JSON.

JSON.parse("string"); // SyntaxError: Unexpected token s
JSON.parse(43); // 43
JSON.parse("43"); // 43
JSON.parse(true); // true
JSON.parse("true"); // true
JSON.parse(false);
JSON.parse("false");
JSON.parse("trueee"); // SyntaxError: Unexpected token e
JSON.parse("{}"); // {}
JSON.parse("[]"); // []

4
Chociaż przydatne odniesienie, jest to specyfikacja konkretnego parsera JSON (zdefiniowanego w standardzie ECMAScript), a nie samego formatu. Witryna json.org wyraźnie stwierdza, że ​​JSON jest „całkowicie niezależny od języka”, więc nie ma jednego poprawnego parsera.
IMSoP

1
JavaScript / ECMAScipt jest inspiracją dla JSON i jego użytkownikiem, ale nie jego „domem”. JSON został wyprowadzony z notacji literału obiektu we (wszystkich wcześniejszych wersjach) ECMAScript, ale nie jest z nim identyczny. JSON.parseFunkcja dodano następnie do nowszych wersjach standardu ECMAScript opartej na gramatyce Crockforda i RFC.
IMSoP

4
Powinieneś to zrobićJSON.parse("\"string\"");
ericbn

4

JSON to skrót od JavaScript Object Notation. Tylko {}i []zdefiniuj obiekt Javascript. Inne przykłady to literały wartości. W JavaScript istnieją typy obiektów do pracy z tymi wartościami, ale wyrażenie"string" jest reprezentacją wartości literału w kodzie źródłowym, a nie obiektem.

Pamiętaj, że JSON to nie JavaScript. Jest to notacja reprezentująca dane. Ma bardzo prostą i ograniczoną strukturę. Dane JSON są uporządkowane przy użyciu{},:[] znaków. W tej strukturze można używać tylko wartości literałów.

Serwer może w odpowiedzi podać opis obiektu lub wartość literalną. Wszystkie parsery JSON powinny obsługiwać tylko wartość literału, ale tylko jedną wartość. JSON może reprezentować tylko jeden obiekt naraz. Tak więc, aby serwer zwracał więcej niż jedną wartość, musiałby utworzyć strukturę jako obiekt lub tablicę.


1
Myślę, że podejście do odpowiedzi z tego kierunku bardziej zagmatwa niż wyjaśnia: pochodzenie nazwy nie ma wpływu na szczegóły standardu, a typy dostępne w JavaScript mogą być inspiracją dla typów w JSON, ale nie ma takiego wymagania że pasują. Wprowadzenie na json.org wyjaśnia to jasno: „JSON to format tekstowy całkowicie niezależny od języka”
IMSoP

@IMSoP Całkowicie się zgadzam. Zmieszałem typy JavaScript z JSON i to nie jest poprawne. Zaktualizuję odpowiedź.
Reactgular

2

Tak, tak, tak, tak i tak. Wszystkie z nich są prawidłowymi literałami wartości JSON.

Jednak oficjalny dokument RFC 4627 stwierdza:

Tekst JSON to serializowany obiekt lub tablica.

Zatem cały „plik” powinien składać się z obiektu lub tablicy jako zewnętrznej struktury, która oczywiście może być pusta. Jednak wiele parserów JSON akceptuje również wartości pierwotne jako dane wejściowe.


-1
var x;
JSON.stringify(x); // will output "{}"

Twoja odpowiedź brzmi, "{}"co oznacza pusty obiekt.


FWIW, w Chrome to daje undefined, a nie "{}" `
Matt

-2

Wystarczy postępować zgodnie ze schematami kolejowymi zamieszczonymi na stronie json.org . [] i {} to minimalne możliwe poprawne obiekty JSON. Więc odpowiedź to [] i {}.


3
To nie jest FSM, to gramatyka. I nie wydaje się wskazywać, która produkcja jest regułą startu. Gdyby zasady startu były arrayi objectmiałbyś rację, ale rozsądnie jest oczekiwać, valueże będziesz początkiem.

Wydaje mi się jednak dość proste. Douglas Crockford tak ich nazywa i zawsze zaczynamy od lewej i podążamy śladami w prawo. Najmniejsza ścieżka daje minimalny prawidłowy kod JSON.
Hrishi

2
Nie chodzi o twoją interpretację jakiejś konkretnej reguły gramatycznej, której się sprzeciwiam, chodzi o to, że wybrałeś dwie reguły i założyłeś, że jedna może zacząć się tylko od nich, a nie od innych. Jeśli spojrzysz na valuesregułę zamiast (lub oprócz) reguł arrayi object, wówczas samodzielne liczby i ciągi znaków są prawidłowym dokumentem JSON.

-1. Po pierwsze, jak wskazuje @delnan, nic na diagramach w serwisie json.org nie sugeruje, że pełny tekst JSON musi być obiektem lub tablicą; wybrałeś te dwa arbitralnie, nie opierając się na niczym w json.org. Po drugie, przeglądanie terminologii: []chociaż poprawny tekst JSON pod każdą specyfikacją, która kiedykolwiek miała opinię w tej sprawie, nie jest „prawidłowym obiektem JSON”, ponieważ nie jest obiektem JSON. „Obiekt” w JSON odnosi się konkretnie do {}notacji; Tablice JSON nie są obiektami JSON.
Mark Amery,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.