ใน JSON ทำไมแต่ละชื่อจึงถูกยกมา?


91

ข้อมูลจำเพาะของ JSONบอกว่า JSON เป็นวัตถุหรืออาร์เรย์ ในกรณีของวัตถุ

โครงสร้างออบเจ็กต์แสดงเป็นคู่ของวงเล็บปีกกาล้อมรอบคู่ชื่อ / ค่าที่เป็นศูนย์หรือมากกว่า (หรือสมาชิก) ชื่อคือสตริง ...

และต่อมาข้อมูลจำเพาะบอกว่าสตริงล้อมรอบด้วยเครื่องหมายคำพูด

ทำไม?

ด้วยประการฉะนี้

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

และไม่

{Property1:"Value1",Property2:18}

คำถามที่ 1 : ทำไมไม่อนุญาตให้ชื่อในคู่ชื่อ / ค่าเป็นตัวระบุที่ไม่มีเครื่องหมายคำพูด


คำถามที่ 2 : มีความแตกต่างทางความหมายระหว่างสองการแสดงข้างต้นเมื่อประเมินใน Javascript หรือไม่?


1
@ Bruno: คุณสามารถพูดถึง XML ในลักษณะเดียวกันได้ ... และน่าเศร้าที่บางคนอาจพยายามใช้ XML เป็นภาษาโปรแกรม ...
Mike DeSimone

2
+1 ... ดูเหมือนจะมีความขัดแย้งที่แปลกประหลาด .... "ด้วยเครื่องหมายคำพูด" ทำให้เป็น JSON มาตรฐาน แต่จะใช้ไม่ได้กับeval()(เช่นจาวาสคริปต์)
skaffman

2
@bruno เลขที่ ถ้าคุณขยายมันจะกลายเป็น "ใน Javascript Object Notation" ซึ่งก็ใช้ได้
Dave Archer

2
@skaffman - จะทำงานเมื่อมีการพัฒนาใน JavaScript
Quentin

1
@Bruno - JSON เป็นรูปแบบข้อมูล "ใน JSON" หมายถึง - ด้วยข้อมูลที่จัดรูปแบบตามข้อมูลจำเพาะ
Cheeso

คำตอบ:


57

คำถามที่ 1: ทำไมไม่อนุญาตให้ชื่อในคู่ชื่อ / ค่าเป็นตัวระบุที่ไม่มีเครื่องหมายคำพูด

ปรัชญาการออกแบบของ JSON คือ "Keep it simple"

"อ้างชื่อด้วย""ง่ายกว่า"คุณสามารถอ้างชื่อโดยมี"หรือ'แต่ไม่จำเป็นต้องทำเว้นแต่ว่าจะมีอักขระบางตัว (หรือชุดอักขระที่จะทำให้เป็นคีย์เวิร์ด) และ'หรือ"อาจต้องยกมาขึ้นอยู่กับ ในสิ่งที่ตัวคั่นคุณเลือก"

คำถามที่ 2: มีความแตกต่างทางความหมายระหว่างสองการแสดงข้างต้นเมื่อประเมินใน Javascript

ไม่ได้ใน JavaScript จะเหมือนกัน


3
ไม่มันไม่ถูกต้อง CMS มีคำตอบที่ถูกต้อง คำตอบนี้เป็นเพียงผลข้างเคียงที่ดีของเหตุผลที่แท้จริง นอกเหนือจากการอธิบายให้ง่ายขึ้นแล้วการเขียนตัวแยกวิเคราะห์ยังง่ายกว่าเนื่องจากคุณสามารถใช้กฎการแยกวิเคราะห์ซ้ำสำหรับสตริงบนตัวระบุ
Breton

และนอกเหนือจากนั้นมีความแตกต่างทางความหมายเล็กน้อยหากตัวระบุเป็นคำสงวนจะถูกตีความว่าเป็นคำนั้นแทนที่จะเป็นตัวระบุ
Breton

2
+1 ในคำตอบของ CMS นั่นถูกต้อง เครื่องหมายคำพูดคู่ไม่ใช่รูปแบบของรหัส แต่คุณต้องการหลีกเลี่ยงคำสงวนเป็นคีย์ในวัตถุ ตัวอย่างเช่น: {property1: "abc", this: "def"} ผิด (นี่คือคีย์เวิร์ดที่สงวนไว้)
Sorin Mocanu

คำถามที่ 2 : ความแตกต่างเล็ก ๆ ใน Javascript เมื่อใช้JSON.parseฟังก์ชั่นJSON.parse('{"a":1}') ทำงานได้ดีทำไมJSON.parse('{a:1}')จะเพิ่มข้อยกเว้น
nhnghia

@nhnghia - คำถามที่ 2 เกี่ยวกับการประเมินซอร์สโค้ดเป็น JavaScriptไม่ใช่ JSON JSON.parseเป็นตัวแยกวิเคราะห์ JSON ที่ใช้งานใน JavaScript ไม่ใช่ตัวแยกวิเคราะห์ JavaScript
Quentin

134

ฉันฝากคำพูดจากงานนำเสนอที่ Douglas Crockford (ผู้สร้างมาตรฐาน JSON) ให้กับ Yahoo

เขาพูดถึงวิธีที่เขาค้นพบ JSON และอื่น ๆ อีกมากมายว่าทำไมเขาถึงตัดสินใจใช้คีย์ที่ยกมา :

.... นั่นคือตอนที่เราค้นพบปัญหาชื่อที่ไม่ได้ระบุ ปรากฎว่า ECMA Script 3 มีนโยบายตีคำสงวน คำสงวนจะต้องถูกยกมาในตำแหน่งสำคัญซึ่งเป็นเรื่องที่น่ารำคาญจริงๆ เมื่อฉันเริ่มกำหนดสิ่งนี้ให้เป็นมาตรฐานฉันไม่ต้องการให้คำสงวนทั้งหมดอยู่ในมาตรฐานเพราะมันจะดูโง่จริงๆ

ตอนนั้นฉันพยายามโน้มน้าวผู้คนใช่คุณสามารถเขียนแอปพลิเคชันใน JavaScript มันใช้งานได้จริงและเป็นภาษาที่ดี ฉันไม่อยากจะพูดในเวลาเดียวกัน: และดูสิ่งที่โง่เขลาจริงๆที่พวกเขาทำ! ดังนั้นฉันจึงตัดสินใจว่าเรามาพูดถึงคีย์แทน
แบบนั้นเราคงไม่ต้องบอกใครหรอกว่ามันเป็นอย่างไร

นั่นเป็นเหตุผลที่จนถึงทุกวันนี้คีย์จึงถูกยกมาใน JSON

คุณสามารถค้นหาวิดีโอที่สมบูรณ์และหลักฐานการศึกษาที่นี่


อืมม ... ผู้สร้างมาตรฐาน JSON?! ฉันเชื่อว่านั่นเป็นการคุยโว JSON คือ JavaScript Object Notation และมาจากข้อมูลจำเพาะ Javascript (ECMA)
Sorin Mocanu

42
@Sorin: อย่าสับสน JSON กับ JavaScript Object literals JSON เป็นรูปแบบการแลกเปลี่ยนข้อมูลที่ไม่เชื่อเรื่องพระเจ้าซึ่งเสนอโดย Crockford ในปี 2549 ( tools.ietf.org/html/rfc4627 ) ไวยากรณ์ของมันแตกต่างจากตัวอักษร JavaScript Object ( bclary.com/2004/11/07/#a-11.1 0.5 ) โดยทั่วไปโดยการอนุญาตให้เพียงสตริงคีย์และค่าที่ต้องเป็นวัตถุ , อาเรย์ , จำนวน , สตริงหรือหนึ่งในรายชื่อที่แท้จริงต่อไปนี้: เท็จ , null จริง ตัวอักษรของวัตถุใน JavaScript สามารถมีคีย์เป็นตัวบ่งชี้ , ตัวอักษรสตริงหรือตัวเลขตามตัวอักษรและค่าสามารถเป็นนิพจน์ประเภทใดก็ได้...
Christian C. Salvadó

@CMS และ JavaScript ของวันนี้อนุญาตให้ใช้ตัวระบุชวเลขภายในนิพจน์ตัวสร้างอ็อบเจ็กต์เช่น{ a }โดยที่คุณสมบัติ 'a' คัดลอกค่าของตัวแปรส่วนกลางหรือโลคัล 'a'
Hydroper

@CMS และยังมีคีย์ที่คำนวณด้วย:{[key]: value}
Hydroper

0

:อนุญาตให้ใช้ทั้งช่องว่างและช่องว่างในตัวระบุ หากไม่มีเครื่องหมายคำพูดสิ่งนี้จะทำให้เกิดความคลุมเครือเมื่อพยายามระบุว่าอะไรเป็นตัวระบุ


0

ในวัตถุจาวาสคริปต์สามารถใช้เช่นแฮช / แฮชแท็กกับคู่คีย์

อย่างไรก็ตามหากคีย์ของคุณมีอักขระที่จาวาสคริปต์ไม่สามารถโทเค็นเป็นชื่อได้คีย์นั้นจะล้มเหลวเมื่อพยายามเข้าถึงเช่นคุณสมบัติบนวัตถุแทนที่จะเป็นคีย์

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.

บางครั้งตัวระบุอาจมีอักขระที่ไม่สามารถประเมินเป็นโทเค็น / ตัวระบุในจาวาสคริปต์ได้ดังนั้นจึงเป็นการดีที่สุดที่จะใส่ตัวระบุทั้งหมดในสตริงเพื่อความสอดคล้องกัน


-2

ฉันคิดว่าคำตอบที่ถูกต้องสำหรับคำถามของ Cheeso คือการนำไปใช้งานนั้นเหนือกว่าเอกสาร ไม่ต้องใช้สตริงเป็นคีย์อีกต่อไป แต่เป็นอย่างอื่นซึ่งอาจเป็นสตริง (เช่นยกมา) หรือ (อาจ) อะไรก็ได้ที่ใช้เป็นชื่อตัวแปรได้ซึ่งฉันจะเดาว่าหมายถึงเริ่มต้นด้วยตัวอักษร _ หรือ $ และรวมเฉพาะตัวอักษรตัวเลขและ $ และ _

ฉันต้องการทำให้ส่วนที่เหลือง่ายขึ้นสำหรับคนถัดไปที่เข้ามาเยี่ยมชมคำถามนี้ด้วยความคิดเดียวกับที่ฉันทำ นี่คือเนื้อ:

ชื่อตัวแปรจะไม่ถูกสอดแทรกใน JSON เมื่อใช้เป็นคีย์ออบเจ็กต์ (ขอบคุณ Friedo!)

Breton โดยใช้ "ตัวระบุ" แทน "คีย์" เขียนว่า "ถ้าตัวระบุเป็นคำสงวนจะถูกตีความว่าเป็นคำนั้นแทนที่จะเป็นตัวระบุ" นี่อาจเป็นความจริง แต่ฉันลองแล้วโดยไม่มีปัญหาใด ๆ :

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

=> 6

เกี่ยวกับการใช้คำพูด Quentin เขียนว่า "... แต่คุณไม่จำเป็นต้องทำเว้นแต่ [คีย์] จะมีอักขระบางตัว (หรือชุดอักขระที่จะทำให้เป็นคีย์เวิร์ด)"

ฉันพบว่าส่วนเดิม (อักขระบางตัว) เป็นจริงโดยใช้เครื่องหมาย @ (อันที่จริงฉันคิดว่า $ และ _ เป็นอักขระเดียวที่ไม่ทำให้เกิดข้อผิดพลาด):

var a = {a@b:1};

=> ข้อผิดพลาดทางไวยากรณ์

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

=> 1

แต่วงเล็บเกี่ยวกับคำหลักดังที่ฉันแสดงไว้ข้างต้นไม่เป็นความจริง

สิ่งที่ฉันต้องการใช้งานได้เนื่องจากข้อความระหว่างช่องเปิด {และเครื่องหมายจุดคู่หรือระหว่างเครื่องหมายจุลภาคและเครื่องหมายจุดคู่สำหรับคุณสมบัติที่ตามมาถูกใช้เป็นสตริงที่ไม่มีเครื่องหมายคำพูดเพื่อสร้างคีย์วัตถุหรือตามที่ Friedo ใส่ไว้ชื่อตัวแปรที่นั่นไม่มี ' t ได้รับการแก้ไข:

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

=> ABC123


-3

หาก json อธิบายถึงวัตถุในทางปฏิบัติคุณจะได้รับสิ่งต่อไปนี้

var foo = {};

var bar = 1;

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

ถ้าอย่างนั้น

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

ดังนั้นแม้ว่าตัวอย่างของคุณจะให้ผลลัพธ์เหมือนกัน แต่สิ่งที่เทียบเท่าใน "รหัสดิบ" จะไม่ อาจเป็นเพราะเหตุใด ?? ดันโนแค่ความคิด


3
@David ชื่อตัวแปรจะไม่ถูกแทรกใน JS เมื่อใช้เป็นคีย์ออบเจ็กต์ { bar: 'goodbye' }จะไม่ได้ตั้งชื่อคีย์ค่าของมันจะเป็นเพียงbar barคนอื่น ๆ พูดถูกเกี่ยวกับเหตุผลที่ข้อกำหนดต้องใช้เครื่องหมายคำพูดนั่นคือเพื่อหลีกเลี่ยงความขัดแย้งของคำหลักและอักขระพิเศษ
ทอด

-3

อาจลดขนาดข้อมูลหากอนุญาตให้ใส่เครื่องหมายคำพูดบนชื่อเมื่อจำเป็นเท่านั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.