Czy klucze JSON muszą być otoczone cudzysłowami?

235

Przykład: czy następujący kod jest poprawny w stosunku do zgodny ze specyfikacją JSON ?

{
    precision: "zip"
}

Czy powinienem zawsze używać następującej składni? (A jeśli tak, to dlaczego?)

{
    "precision": "zip"
}

Tak naprawdę nie znalazłem czegoś na ten temat w specyfikacjach JSON. Chociaż w swoich przykładach używają cudzysłowów wokół swoich kluczy.

christianvuerings
źródło

Odpowiedzi:

147

Tak, potrzebujesz cudzysłowów. Ma to na celu uproszczenie i uniknięcie konieczności stosowania innej metody zmiany znaczenia dla słów kluczowych zarezerwowanych w javascript, tj {for:"foo"}.

cobbal
źródło
12
Cytaty nie są prostsze w wielu sytuacjach, takich jak pliki konfiguracyjne edytowane ręcznie. Niefortunne jest to, że JSON jest używany (i niewłaściwie używany) jako prawie uniwersalny format wymiany, ponieważ ma funkcje specyficzne dla Javascript.
Miguel
12
Prawdziwy powód - sprawdź również tę odpowiedź - stackoverflow.com/questions/4201441/…
TechMaze
3
Tl; dr: nie chcieli zajmować się ograniczeniem ECMAScript dla (niecytowanych) zarezerwowanych słów kluczowych jako kluczy, więc po prostu wymagali cytowania wszystkich kluczy.
BallpointBen,
136

Poprawne jest używanie ciągów jako klucza. Oto fragment RFC 4627 - Aplikacja / json Media Type dla JavaScript Object Notation (JSON)

2.2 Obiekty

Struktura obiektu jest reprezentowana jako para nawiasów klamrowych otaczających zero lub więcej par nazwa / wartość (lub członków). Nazwa to ciąg znaków . Po każdej nazwie występuje pojedynczy dwukropek, oddzielający nazwę od wartości. Pojedynczy przecinek oddziela wartość od następującej nazwy. Nazwy w obiekcie POWINNY być unikalne.

object = begin-object [ member *( value-separator member ) ] end-object

member = string name-separator value

[...]

2.5 Smyczki

Reprezentacja ciągów znaków jest podobna do konwencji używanych w rodzinie języków programowania C. Ciąg zaczyna się i kończy znakiem cudzysłowu. [...]

string = quotation-mark *char quotation-mark

quotation-mark = %x22 ; "

Przeczytaj cały RFC tutaj .

PatrikAkerstrand
źródło
11
I dokończyć myśl, sekcja 2.5 mówi: A string begins and ends with quotation marks..
rakslice,
13

Od 2.2. Obiekty

Struktura obiektu jest reprezentowana jako para nawiasów klamrowych otaczających zero lub więcej par nazwa / wartość (lub członków). Nazwa to ciąg znaków.

i od 2.5. Smyczki

Ciąg zaczyna się i kończy znakiem cudzysłowu.

Powiedziałbym więc, że zgodnie ze standardem: tak, zawsze powinieneś cytować klucz (chociaż niektóre parsery mogą być bardziej wybaczające)

Cebjyre
źródło
7

Tak, cytaty są obowiązkowe. http://json.org/ mówi:

string
    ""
    " chars "

źródło
0

Tak, robią. Ale jeśli potrzebujesz inaczej, sprawdź JSON5 .

JSON5 to nadzbiór JSON, który umożliwia składnię ES5, w tym:

  • niecytowane klucze własności
  • ciągi cudzysłowu, znaki specjalne i wieloliniowe
  • alternatywne formaty liczb
  • komentarze
  • dodatkowe białe znaki

Implementacja referencyjna JSON5 ( json5pakiet npm ) zapewnia JSON5obiekt, który ma parsei stringifymetody z tymi samymi argumentami i semantyką jak obiekt wbudowany JSON.

Inigo
źródło
-2

Ponieważ możesz umieścić kropkowaną notację „parent.child” i nie musisz umieszczać nadrzędnej [„child”], która jest również ważna i przydatna, powiedziałbym, że obie metody są technicznie dopuszczalne. Wszystkie parsery powinny działać w obie strony w porządku. Jeśli twój parser nie potrzebuje cudzysłowów na klawiszach, prawdopodobnie lepiej nie wstawiać ich (oszczędza miejsce). Sensowne jest nazywanie ich ciągami, ponieważ takie są, a ponieważ nawiasy kwadratowe dają możliwość używania wartości dla kluczy, w zasadzie nie ma sensu. W Json możesz umieścić ...

>var keyName = "someKey";
>var obj = {[keyName]:"someValue"};

>obj
Object {someKey: "someValue"}

w porządku bez problemów, jeśli potrzebujesz wartości dla klucza i żaden cytowany nie będzie działał, więc jeśli nie, nie możesz, więc nie będziesz tak „nie potrzebował cudzysłowów na kluczach”. Nawet jeśli słusznie jest powiedzieć, że są technicznie sznurkami. Logika i użycie argumentują inaczej. Oficjalnie nie wypisuje też obiektu {"someKey": "someValue"} dla obj w naszym przykładzie z konsoli dowolnej przeglądarki.

Mistrzu Jamesie
źródło
2
Zarówno zaakceptowana odpowiedź, jak i RFC, które definiują JSON, mówią, że cytaty są wymagane.
Keith Thompson
To prawda, ale warto zauważyć, że logicznie nie musi. Podejrzewam, że wynik JavaScript Object Notation ze wszystkich konsoli przeglądarki jest nieprawidłowy i powinniśmy powiedzieć komuś, żeby to naprawił. Może to, co konsola przeglądarki wyświetla dla obiektu, nie jest JSON, więc może JSON, jak określa specyfikacja, nie jest potrzebny ani implementowany w ten sposób w większości miejsc. W każdym razie chciałem po prostu przedstawić sprawę, która patrzy na fakty w innym świetle. Naprawdę, może specyfikacja powinna zostać zmieniona, „Cytowane klucze” nie są po prostu potrzebne nigdzie, co jest dla mnie ważne. (Po prostu nie stosuje się go w praktyce).
Mistrz James
2
Mieszasz trzy różne rzeczy: JSON, literały obiektów JavaScript i dane wyjściowe konsoli narzędzi programistycznych przeglądarki. Podczas pisania objw konsoli przeglądarka wyświetla czytelną dla człowieka reprezentację obiektu. Może wyświetlać go jako dosłowny obiekt (tak jak w twoim przykładzie) lub może użyć innej reprezentacji, nawet interaktywnej. Literały obiektów JavaScript nie wymagają cudzysłowów wokół nazwy klucza, jeśli klucz jest prawidłowym identyfikatorem, a nie słowem zastrzeżonym. Jednak JSON zawsze wymaga cudzysłowów wokół nazw kluczy.
Michael Geary,
3
Jako dalsze przykłady, zamiast pisać objw konsoli, spróbuj JSON.stringify(obj). Teraz zobaczysz prawidłową reprezentację JSON obiektu wraz z cytowaną nazwą klucza. I odwrotnie, aby sprawdzić, czy łańcuch jest prawidłowy JSON, spróbuj JSON.parse(string). Jeśli klucze nie zostaną podane, spowoduje to wyjątek. Na przykład JSON.parse('{"a":"b"}')odniesie sukces, ale JSON.parse('{a:"b"}')zakończy się niepowodzeniem.
Michael Geary,
1
OTOH, twoje użycie var obj = {[keyName]:"someValue"};jest bardzo interesujące! Nie wiedziałem, że możesz to zrobić w dosłownym obiekcie JavaScript. Trochę sprawdzania pokazuje, że jest to coś nowego w ES6 - nie można tego zrobić w ES5.
Michael Geary,