w formacie JSON, dlaczego każda nazwa jest cytowana?


91

Specyfikacja JSON mówi, że JSON jest obiektem lub tablicą. W przypadku przedmiotu,

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. ...

A później specyfikacja mówi, że ciąg jest ujęty w cudzysłów.

Czemu?

A zatem,

{"Property1":"Value1","Property2":18}

i nie

{Property1:"Value1",Property2:18}

Pytanie 1 : dlaczego nie pozwolić, aby nazwa w parach nazwa / wartość była identyfikatorami niecytowanymi?


Pytanie 2 : Czy istnieje różnica semantyczna między dwiema powyższymi reprezentacjami, gdy ocenia się je w JavaScript?


1
@Bruno: Możesz mówić o XML w ten sam sposób ... i niestety, niektórzy mogą próbować używać XML jako języka programowania ...
Mike DeSimone

2
+1 ... wygląda na osobliwą sprzeczność ... "w cudzysłowie" sprawia, że ​​jest to standardowy JSON, ale nie działa z eval()(tj. Javascript).
skaffman

2
@bruno, nie. jeśli go rozwiniesz, zmieni się na „in Javascript Object Notation”, co jest w porządku
Dave Archer,

2
@skaffman - Będzie działać po ocenie w JavaScript.
Quentin

1
@Bruno - JSON to format danych. „W formacie JSON” oznacza - z danymi sformatowanymi zgodnie ze specyfikacją.
Cheeso

Odpowiedzi:


57

Pytanie 1: dlaczego nie pozwolić, aby nazwa w parach nazwa / wartość była identyfikatorami niecytowanymi?

Filozofia projektowania JSON to „Keep it simple”

„Cytuje nazwy z " jest dużo prostsze niż „Można przytoczyć nazwiska z "albo ', ale nie muszą, jeżeli nie zawiera niektórych znaków (lub zestawy znaków, które sprawiają, że kluczowe) i 'czy "może muszą być notowane w zależności od wybranego separatora ” .

Pytanie 2: Czy istnieje różnica semantyczna między dwiema powyższymi reprezentacjami, gdy ocenia się je w JavaScript?

Nie. W JavaScript są identyczne.


3
Nie, to nie jest poprawne. CMS ma poprawną odpowiedź. Ta odpowiedź to tylko miły efekt uboczny prawdziwego powodu. Oprócz prostszego wyjaśnienia, prostsze jest również napisanie parsera, ponieważ możesz ponownie użyć reguł analizy dla ciągów na identyfikatorach.
Breton,

a poza tym istnieje niewielka różnica semantyczna polegająca na tym, że jeśli identyfikator jest słowem zastrzeżonym, jest interpretowany jako to słowo, a nie jako identyfikator.
Breton,

2
+1 na odpowiedź CMS, to prawda. Podwójne cudzysłowy nie są konwencją kodu, ale chcesz uniknąć zarezerwowanych słów jako kluczy w obiekcie. Na przykład: {property1: "abc", this: "def"} jest NIEPRAWIDŁOWE (to jest zastrzeżone słowo kluczowe)
Sorin Mocanu

Pytanie 2 : niewielka różnica w JavaScript, gdy za pomocą JSON.parsefunkcji: JSON.parse('{"a":1}') działa dobrze , to dlaczego JSON.parse('{a:1}')będzie wyjątek .
nhnghia

@nhnghia - Pytanie 2 dotyczy oceny kodu źródłowego jako JavaScript , a nie JSON. JSON.parseto parser JSON zaimplementowany w JavaScript, nie jest parserem JavaScript.
Quentin

134

Zostawiam cytat z prezentacji, którą Douglas Crockford (twórca standardu JSON) przekazał Yahoo.

Opowiada o tym, jak odkrył JSON i między innymi, dlaczego zdecydował się użyć cudzysłowów :

.... Wtedy odkryliśmy problem z nazwami bez cytatów. Okazuje się, że ECMA Script 3 ma politykę dotyczącą słów zastrzeżonych. Zastrzeżone słowa należy cytować w pozycji kluczowej, co jest naprawdę uciążliwe. Kiedy doszedłem do sformułowania tego w standardzie, nie chciałem umieszczać wszystkich zastrzeżonych słów w standardzie, ponieważ wyglądałoby to naprawdę głupio.

W tamtym czasie starałem się przekonać ludzi: tak, możesz pisać aplikacje w JavaScript, to naprawdę zadziała i to jest dobry język. Nie chciałem więc jednocześnie powiedzieć: i spójrz na tę naprawdę głupią rzecz, którą zrobili! Postanowiłem więc zamiast tego zacytować klucze.
W ten sposób nie musimy nikomu mówić o tym, jak to jest.

Dlatego do dziś klucze są cytowane w formacie JSON.

Możesz znaleźć cały film i transkrypcję tutaj .


Ummm ... twórca standardu JSON ?! Uważam, że to przesada. JSON to JavaScript Object Notation i pochodzi ze specyfikacji Javascript (ECMA).
Sorin Mocanu,

42
@Sorin: Nie myl JSON z literałami obiektów JavaScript. JSON to format wymiany danych niezależny od języka , zaproponowany przez Crockforda w 2006 roku ( tools.ietf.org/html/rfc4627 ), jego gramatyka różni się od literałów obiektów JavaScript ( bclary.com/2004/11/07/#a-11.1 .5 ), po prostu zezwalając tylko na klucze łańcuchowe i wartości MUSZĄ być obiektem , tablicą , liczbą , łańcuchem lub jedną z następujących nazw literałów: false , null true . Literały obiektów w JavaScript mogą mieć klucze jako identyfikatory , literały ciągów lub liczbowe, a wartością może być dowolny typ wyrażenia ...
Christian C. Salvadó

@CMS A dzisiejszy JavaScript dopuszcza skrócone identyfikatory wewnątrz wyrażeń konstruktora obiektów, np .: { a }, gdzie właściwość „a” kopiuje wartość zmiennej globalnej lub lokalnej „a”.
Hydroper

@CMS Są też klucze obliczeniowe:{[key]: value}
Hydroper

0

:W identyfikatorach dozwolone są zarówno znaki, jak i spacje. Bez cudzysłowów spowodowałoby to niejednoznaczność przy próbie ustalenia, co dokładnie stanowi identyfikator.


0

W javascript obiekty mogą być używane jak hash / hashtable z parami kluczy.

Jeśli jednak twój klucz zawiera znaki, których javascript nie może tokenizować jako nazwy, próba uzyskania dostępu nie powiedzie się, jak właściwość obiektu, a nie klucz.

var test  = {};
test["key"] = 1;
test["#my-div"] = "<div> stuff </div>";

// test = { "key": 1, "#my-div": "<div> stuff </div>" };

console.log(test.key);           // should be 1
console.log(test["key"]);        // should be 1
console.log(test["#my-div"]);    // should be "<div> stuff </div>";
console.log(test.#my-div);       // would not work.

Identyfikatory mogą czasami zawierać znaki, których nie można ocenić jako token / identyfikator w javascript, dlatego najlepiej jest umieścić wszystkie identyfikatory w ciągach, aby zachować spójność.


-2

Myślę, że właściwą odpowiedzią na pytanie Cheeso jest to, że implementacja przerosła dokumentację. Nie wymaga już łańcucha jako klucza, ale raczej coś innego, co może być ciągiem znaków (tj. W cudzysłowie) lub (prawdopodobnie) czymkolwiek, co może być użyte jako nazwa zmiennej, co, jak sądzę, oznacza rozpoczęcie od litery, _ lub $ i zawierają tylko litery, cyfry oraz znaki $ i _.

Resztę chciałem uprościć następnej osobie, która zadaje to pytanie z tym samym pomysłem, co ja. Oto mięso:

Nazwy zmiennych nie są interpolowane w formacie JSON, gdy są używane jako klucz obiektu (dzięki Friedo!)

Breton, używając „identyfikatora” zamiast „klucza”, napisał, że „jeśli okaże się, że identyfikator jest słowem zastrzeżonym, jest on interpretowany jako to słowo, a nie jako identyfikator”. Może to prawda, ale próbowałem bez problemu:

var a = {do:1,long:2,super:3,abstract:4,var:5,break:6,boolean:7};
a.break

=> 6

O używaniu cudzysłowów Quentin napisał „... ale nie musisz tego robić, chyba że [klucz] zawiera określone znaki (lub kombinacje znaków, które uczyniłyby z niego słowo kluczowe)”

Okazało się, że pierwsza część (niektóre znaki) jest prawdą, używając znaku @ (w rzeczywistości myślę, że $ i _ to jedyne znaki, które nie powodują błędu):

var a = {a@b:1};

=> Błąd składni

var a = {"a@b":1};
a['a@b']

=> 1

ale nawias dotyczący słów kluczowych, jak pokazałem powyżej, nie jest prawdziwy.

To, co chciałem, działa, ponieważ tekst między początkiem {a dwukropkiem lub między przecinkiem a dwukropkiem dla kolejnych właściwości jest używany jako niecytowany ciąg do utworzenia klucza obiektu lub, jak ujął to Friedo, nazwa zmiennej nie robi t zostanie interpolowany:

var uid = getUID();
var token = getToken();            // Returns ABC123
var data = {uid:uid,token:token};
data.token

=> ABC123


-3

Jeśli json opisuje obiekty, w praktyce otrzymujesz:

var foo = {};

var bar = 1;

foo["bar"] = "hello";
foo[bar] = "goodbye";

więc wtedy,

foo.bar == "hello";
foo[1] == "goodbye" // in setting it used the value of var bar

więc nawet jeśli twoje przykłady dadzą ten sam wynik, ich odpowiedniki w „surowym kodzie” nie. Może to dlatego?? nie wiem, tylko pomysł.


3
@David, nazwy zmiennych nie są interpolowane w JS, gdy są używane jako klucz obiektu. { bar: 'goodbye' }nie ustawi nazwy klucza na wartość bar, po prostu będzie bar. Inni mają rację co do powodu, dla którego specyfikacja wymaga cudzysłowów: ma to na celu uniknięcie konfliktów słów kluczowych i znaków specjalnych.
Friedo

-3

Może to zmniejszyć rozmiar danych, jeśli cudzysłowy w nazwie są dozwolone tylko wtedy, gdy jest to konieczne

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.