di JSON, Mengapa setiap nama dikutip?

91

Spesifikasi JSON mengatakan bahwa JSON adalah objek atau larik. Dalam kasus sebuah benda,

Struktur objek direpresentasikan sebagai sepasang tanda kurung kurawal yang mengelilingi nol atau lebih pasangan nama / nilai (atau anggota). Nama adalah string. ...

Dan kemudian, spesifikasi mengatakan bahwa string diapit tanda kutip.

Mengapa?

Jadi,

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

dan tidak

{Property1:"Value1",Property2:18}

Pertanyaan 1 : Mengapa tidak mengizinkan nama dalam pasangan nama / nilai menjadi pengenal tanpa tanda kutip?


Pertanyaan 2 : Apakah ada perbedaan semantik antara dua representasi di atas, saat dievaluasi dalam Javascript?

Cheeso
sumber
1
@Bruno: Anda dapat berbicara tentang XML dengan cara yang sama ... dan sayangnya, beberapa di luar sana mungkin mencoba menggunakan XML sebagai bahasa pemrograman ...
Mike DeSimone
2
+1 ... sepertinya kontradiksi yang aneh .... "dengan tanda kutip" menjadikannya JSON standar, tetapi tidak berfungsi dengan eval()(mis. Javascript).
Skaffman
2
@bruno, tidak. jika Anda mengembangkannya, itu menjadi "dalam Javascript Object Notation" yang tidak masalah
Dave Archer
2
@skaffman - Ini akan berfungsi saat ditampilkan dalam JavaScript.
Quentin
1
@Bruno - JSON adalah format data. "Dalam JSON" artinya - dengan data yang diformat sesuai dengan spesifikasi.
Cheeso

Jawaban:

57

Pertanyaan 1: Mengapa tidak mengizinkan nama dalam pasangan nama / nilai menjadi pengenal tanpa tanda kutip?

Filosofi desain JSON adalah "Tetap sederhana"

"Nama kutipan dengan "" jauh lebih sederhana daripada "Anda dapat mengutip nama dengan "atau 'tetapi Anda tidak perlu, kecuali jika mengandung karakter tertentu (atau kombinasi karakter yang akan menjadikannya kata kunci) dan 'atau "mungkin perlu dikutip tergantung pada pembatas apa yang Anda pilih " .

Pertanyaan 2: Apakah ada perbedaan semantik antara dua representasi di atas, saat dievaluasi dalam Javascript?

Tidak. Dalam JavaScript, keduanya identik.

Quentin
sumber
3
Tidak, itu tidak benar. CMS punya jawaban yang benar. Jawaban ini hanyalah efek samping yang bagus dari alasan yang sebenarnya. Selain lebih sederhana untuk dijelaskan, itu juga lebih sederhana untuk menulis parser, karena Anda dapat menggunakan kembali aturan parse untuk string pada pengenal.
Breton
dan selain itu, ada sedikit perbedaan semantik di mana jika pengenal kebetulan adalah kata yang dicadangkan, itu diartikan sebagai kata itu dan bukan sebagai pengenal.
Breton
2
+1 pada jawaban CMS, itu benar. Tanda kutip ganda bukanlah konvensi kode, tetapi Anda ingin menghindari kata yang dicadangkan sebagai kunci dalam objek. Misalnya: {property1: "abc", this: "def"} SALAH (ini adalah kata kunci yang dipesan)
Sorin Mocanu
Pertanyaan 2 : Perbedaan kecil dalam Javascript saat menggunakan JSON.parsefunction: JSON.parse('{"a":1}') berfungsi dengan baik , mengapa JSON.parse('{a:1}')akan memunculkan pengecualian .
nhnghia
@nhnghia - Pertanyaan 2 adalah tentang mengevaluasi kode sumber sebagai JavaScript , bukan JSON. JSON.parseadalah parser JSON yang diterapkan di JavaScript, ini bukan parser JavaScript.
Quentin
134

Saya meninggalkan kutipan dari presentasi yang diberikan Douglas Crockford (pencipta standar JSON) kepada Yahoo.

Dia berbicara tentang bagaimana dia menemukan JSON, dan di antara hal-hal lain mengapa dia memutuskan untuk menggunakan kunci yang dikutip :

.... Saat itulah kami menemukan masalah nama yang tidak dikutip. ECMA Script 3 ternyata memiliki kebijakan kata khusus yang mendera. Kata yang dicadangkan harus dikutip di posisi kunci, yang benar-benar mengganggu. Ketika saya sempat merumuskan ini menjadi standar, saya tidak ingin harus memasukkan semua kata yang dicadangkan ke dalam standar, karena itu akan terlihat sangat bodoh.

Pada saat itu, saya mencoba meyakinkan orang: ya, Anda dapat menulis aplikasi dalam JavaScript, ini benar-benar akan berfungsi dan itu adalah bahasa yang bagus. Saya tidak ingin mengatakan, lalu, pada saat yang sama: dan lihatlah hal bodoh yang mereka lakukan! Jadi saya memutuskan, sebagai gantinya, mari kita kutip kuncinya.
Dengan begitu, kita tidak perlu memberi tahu siapa pun tentang betapa dahsyatnya itu.

Itulah mengapa, hingga hari ini, kunci dikutip dalam JSON.

Anda dapat menemukan video dan transkrip lengkapnya di sini .

Christian C. Salvadó
sumber
Ummm ... pencipta standar JSON?! Saya percaya itu berlebihan. JSON adalah JavaScript Object Notation dan berasal dari spesifikasi Javascript (ECMA).
Sorin Mocanu
42
@Sorin: Jangan membingungkan JSON dengan literal Objek JavaScript. JSON adalah format pertukaran data bahasa-agnostik, diusulkan oleh Crockford pada tahun 2006 ( tools.ietf.org/html/rfc4627 ), tata bahasanya berbeda dari literal Objek JavaScript ( bclary.com/2004/11/07/#a-11.1 .5 ), pada dasarnya dengan hanya mengizinkan kunci string dan nilainya HARUS berupa objek , larik , angka , string , atau salah satu dari nama literal berikut: false , null true . Literal objek dalam JavaScript dapat memiliki kunci sebagai Pengidentifikasi , literal string , atauAngka literal , dan nilainya dapat berupa semua jenis ekspresi ...
Christian C. Salvadó
@CMS Dan JavaScript hari ini memungkinkan pengidentifikasi singkatan di dalam ekspresi konstruktor objek, misalnya:, di { a }mana properti 'a' menyalin nilai variabel global atau lokal 'a'.
Hydroper
@CMS Dan ada juga kunci yang dihitung:{[key]: value}
Hydroper
0

Baik :dan spasi diizinkan dalam pengidentifikasi. Tanpa tanda kutip, ini akan menyebabkan ambiguitas saat mencoba menentukan apa sebenarnya yang dimaksud dengan pengenal.

Segera.
sumber
0

Dalam objek javascript dapat digunakan seperti hash / hashtable dengan pasangan kunci.

Namun, jika kunci Anda memiliki karakter yang tidak dapat dibuat token oleh javascript sebagai sebuah nama, kunci tersebut akan gagal saat mencoba mengaksesnya seperti properti pada objek, bukan kunci.

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.

pengenal terkadang dapat memiliki karakter yang tidak dapat dievaluasi sebagai token / pengenal dalam javascript, oleh karena itu yang terbaik adalah meletakkan semua pengenal dalam string agar konsisten.

michael herndon
sumber
-2

Saya pikir jawaban yang tepat untuk pertanyaan Cheeso adalah bahwa implementasinya melampaui dokumentasi. Ini tidak lagi membutuhkan string sebagai kuncinya, melainkan sesuatu yang lain, yang bisa berupa string (yaitu dikutip) atau (mungkin) apa pun yang dapat digunakan sebagai nama variabel, yang menurut saya berarti dimulai dengan huruf, _ , atau $, dan hanya menyertakan huruf, angka, dan $ dan _.

Saya ingin menyederhanakan sisanya untuk orang berikutnya yang mengunjungi pertanyaan ini dengan ide yang sama dengan yang saya lakukan. Ini dagingnya:

Nama variabel tidak diinterpolasi di JSON saat digunakan sebagai kunci objek (Terima kasih Friedo!)

Breton, menggunakan "pengenal" bukan "kunci", menulis bahwa "jika pengenal kebetulan adalah kata yang dipesan, itu diartikan sebagai kata itu daripada sebagai pengenal." Ini mungkin benar, tetapi saya mencobanya tanpa masalah:

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

=> 6

Tentang penggunaan tanda kutip, Quentin menulis "... tetapi Anda tidak perlu melakukannya, kecuali [kunci] berisi karakter tertentu (atau kombinasi karakter yang akan menjadikannya kata kunci)"

Saya menemukan bagian sebelumnya (karakter tertentu) benar, menggunakan tanda @ (sebenarnya, saya pikir $ dan _ adalah satu-satunya karakter yang tidak menyebabkan kesalahan):

var a = {a@b:1};

=> Kesalahan sintaks

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

=> 1

tetapi tanda kurung tentang kata kunci, seperti yang saya tunjukkan di atas, tidak benar.

Apa yang saya inginkan berfungsi karena teks antara pembukaan {dan titik dua, atau antara koma dan titik dua untuk properti berikutnya digunakan sebagai string tanpa tanda kutip untuk membuat kunci objek, atau, seperti yang dikatakan Friedo, nama variabel di sana tidak ' t mendapatkan interpolasi:

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

=> ABC123

Dave Scotese
sumber
-3

Jika json mendeskripsikan objek, maka dalam praktiknya Anda mendapatkan yang berikut

var foo = {};

var bar = 1;

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

sehingga kemudian,

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

jadi meskipun contoh Anda menghasilkan hasil yang sama, padanannya dalam "kode mentah" tidak akan. Mungkin itu sebabnya ?? tak tahu, hanya ide.

Dave Archer
sumber
3
@David, nama variabel tidak diinterpolasi di JS saat digunakan sebagai kunci objek. { bar: 'goodbye' }tidak akan menyetel nama kunci menjadi nilai bar, itu hanya akan bar. Yang lain benar tentang alasan mengapa spesifikasi membutuhkan tanda kutip: itu untuk menghindari konflik kata kunci dan karakter khusus.
friedo
-3

Ini dapat mengurangi ukuran data jika kutipan pada nama hanya diperbolehkan jika diperlukan

shashank joshi
sumber