trong JSON, Tại sao mỗi tên được trích dẫn?


91

Thông số JSON nói rằng JSON là một đối tượng hoặc một mảng. Trong trường hợp của một đối tượng,

Cấu trúc đối tượng được biểu diễn dưới dạng một cặp dấu ngoặc nhọn bao quanh không hoặc nhiều cặp tên / giá trị (hoặc thành viên). Tên là một chuỗi. ...

Và sau đó, thông số kỹ thuật nói rằng một chuỗi được bao quanh trong dấu ngoặc kép.

Tại sao?

Vì vậy,

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

và không

{Property1:"Value1",Property2:18}

Câu hỏi 1 : Tại sao không cho phép tên trong cặp tên / giá trị là định danh chưa được trích dẫn?


Câu hỏi 2 : Có sự khác biệt về ngữ nghĩa giữa hai biểu diễn trên, khi được đánh giá trong Javascript không?


1
@Bruno: Bạn có thể nói về XML theo cùng một cách ... và buồn bã, một số trên mạng cũng có thể cố gắng để sử dụng XML như là một ngôn ngữ lập trình ...
Mike Desimone

2
+1 ... nó có vẻ như là một mâu thuẫn đặc biệt .... "với dấu ngoặc kép" làm cho nó chuẩn JSON, nhưng sẽ không hoạt động với eval()(tức là javascript).
skaffman

2
@bruno, không. nếu bạn mở rộng nó, nó trở nên "trong Javascript Object Notation" mà là tốt
Dave Archer

2
@skaffman - Nó sẽ hoạt động khi được đánh giá bằng JavaScript.
Quentin

1
@Bruno - JSON là một định dạng dữ liệu. "Trong JSON" có nghĩa là - với dữ liệu được định dạng theo thông số kỹ thuật.
Cheeso

Câu trả lời:


57

Câu hỏi 1: Tại sao không cho phép tên trong cặp tên / giá trị là định danh chưa được trích dẫn?

Triết lý thiết kế của JSON là "Giữ cho nó đơn giản"

"Trích dẫn tên với "" đơn giản hơn rất nhiều so với "Bạn có thể trích dẫn tên bằng "hoặc 'nhưng bạn không cần phải làm như vậy, trừ khi chúng chứa các ký tự nhất định (hoặc kết hợp các ký tự sẽ khiến nó trở thành từ khóa) và 'hoặc "có thể cần được trích dẫn tùy thuộc về dấu phân cách bạn đã chọn " .

Câu hỏi 2: Có sự khác biệt về ngữ nghĩa giữa hai biểu diễn trên, khi được đánh giá trong Javascript không?

Không. Trong JavaScript, chúng giống hệt nhau.


3
Không, nó không chính xác. CMS có câu trả lời chính xác. Câu trả lời này chỉ là một tác dụng phụ của lý do thực sự. Ngoài việc giải thích đơn giản hơn, việc viết trình phân tích cú pháp cũng đơn giản hơn, vì bạn có thể sử dụng lại các quy tắc phân tích cú pháp cho các chuỗi trên số nhận dạng.
Breton

và bên cạnh đó, có một chút khác biệt về ngữ nghĩa ở chỗ nếu một từ định danh là một từ dành riêng, thì nó được hiểu là từ đó chứ không phải là một định danh.
Breton

2
+1 về câu trả lời của CMS, điều đó chính xác. Dấu ngoặc kép không phải là một quy ước mã, nhưng bạn muốn tránh các từ dành riêng làm khóa trong đối tượng. Ví dụ: {property1: "abc", this: "def"} là SAI (đây là từ khóa dành riêng)
Sorin Mocanu

Câu hỏi 2 : Một sự khác biệt nhỏ trong Javascript khi sử dụng JSON.parsehàm: JSON.parse('{"a":1}') hoạt động tốt , tại sao JSON.parse('{a:1}')sẽ nêu ra một ngoại lệ .
nhnghia

@nhnghia - Câu hỏi 2 là về đánh giá mã nguồn là JavaScript , không phải JSON. JSON.parselà trình phân tích cú pháp JSON được triển khai bằng JavaScript, nó không phải là trình phân tích cú pháp JavaScript.
Quentin

134

Tôi để lại một trích dẫn từ một bài thuyết trình mà Douglas Crockford (người tạo ra tiêu chuẩn JSON) đã đưa cho Yahoo.

Anh ấy nói về cách anh ấy phát hiện ra JSON và trong số những điều khác tại sao anh ấy quyết định sử dụng các khóa được trích dẫn :

.... Đó là khi chúng tôi phát hiện ra vấn đề tên không được trích dẫn. Hóa ra ECMA Script 3 có chính sách từ dành riêng. Những từ dành riêng phải được trích dẫn ở vị trí then chốt, điều này thực sự gây phiền toái. Khi tôi bắt đầu xây dựng điều này thành một tiêu chuẩn, tôi không muốn phải đưa tất cả các từ dành riêng vào tiêu chuẩn, bởi vì nó trông thực sự ngu ngốc.

Vào thời điểm đó, tôi đang cố gắng thuyết phục mọi người: vâng, bạn có thể viết ứng dụng bằng JavaScript, nó thực sự sẽ hoạt động và đó là một ngôn ngữ tốt. Sau đó, tôi không muốn nói: và hãy nhìn vào điều thực sự ngu ngốc mà họ đã làm! Vì vậy, tôi quyết định, thay vào đó, hãy chỉ trích dẫn các phím.
Bằng cách đó, chúng tôi không cần phải nói với bất kỳ ai về nó như thế nào.

Đó là lý do tại sao, cho đến ngày nay, các khóa được trích dẫn trong JSON.

Bạn có thể tìm thấy toàn bộ video và bản ghi ở đây .


Ummm ... người tạo ra tiêu chuẩn JSON ?! Tôi tin rằng đó là một lời nói quá. JSON là ký hiệu đối tượng JavaScript và xuất phát từ thông số kỹ thuật Javascript (ECMA).
Sorin Mocanu

42
@Sorin: Đừng nhầm lẫn JSON với các ký tự của JavaScript Object. JSON là một định dạng trao đổi dữ liệu bất khả tri ngôn ngữ, được đề xuất bởi Crockford vào năm 2006 ( tools.ietf.org/html/rfc4627 ), ngữ pháp của nó khác với các ký tự của JavaScript Object ( bclary.com/2004/11/07/#a-11.1 .5 ), về cơ bản bằng cách chỉ cho phép các khóa chuỗi và các giá trị PHẢI là một đối tượng , mảng , số , chuỗi hoặc một trong các tên chữ sau: false , null true . Các ký tự đối tượng trong JavaScript có thể có các khóa là Mã định danh , ký tự chuỗi hoặcLiterals số , và giá trị có thể là bất kỳ loại biểu ...
Christian C. Salvadó

@CMS Và JavaScript ngày nay cho phép các mã nhận dạng viết tắt bên trong các biểu thức hàm tạo đối tượng, ví dụ:, { a }trong đó thuộc tính 'a' sao chép giá trị của biến toàn cục hoặc biến cục bộ 'a'.
Hydroper

@CMS Và Ngoài ra còn có tính phím:{[key]: value}
Hydroper

0

Cả hai :và khoảng trắng đều được phép trong số nhận dạng. Nếu không có dấu ngoặc kép, điều này sẽ gây ra sự mơ hồ khi cố gắng xác định chính xác những gì cấu thành mã định danh.


0

Trong javascript, các đối tượng có thể được sử dụng như một bảng băm / bảng băm với các cặp khóa.

Tuy nhiên, nếu khóa của bạn có các ký tự mà javascript không thể mã hóa dưới dạng tên, nó sẽ không thành công khi thử truy cập như một thuộc tính trên một đối tượng chứ không phải là một khóa.

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.

số nhận dạng đôi khi có thể có các ký tự không thể được đánh giá là mã thông báo / mã định danh trong javascript, do đó, tốt nhất nên đặt tất cả các số nhận dạng trong chuỗi để có tính nhất quán.


-2

Tôi nghĩ câu trả lời đúng cho câu hỏi của Cheeso là việc triển khai vượt qua tài liệu. Nó không còn yêu cầu một chuỗi làm khóa, mà là một cái gì đó khác, có thể là một chuỗi (tức là được trích dẫn) hoặc (có thể là) bất kỳ thứ gì có thể được sử dụng làm tên biến, mà tôi sẽ đoán nghĩa là bắt đầu bằng một chữ cái, _ , hoặc $, và chỉ bao gồm các chữ cái, số và $ và _.

Tôi muốn đơn giản hóa phần còn lại cho người tiếp theo truy cập câu hỏi này với cùng ý tưởng tôi đã làm. Đây là thịt:

Tên biến không được nội suy trong JSON khi được sử dụng làm khóa đối tượng (Cảm ơn Friedo!)

Breton, sử dụng "số nhận dạng" thay vì "khóa", đã viết rằng "nếu một số nhận dạng tình cờ là một từ dành riêng, nó được hiểu là từ đó chứ không phải là một định danh." Điều này có thể đúng, nhưng tôi đã thử nó mà không gặp bất kỳ sự cố nào:

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

=> 6

Về việc sử dụng dấu ngoặc kép, Quentin đã viết "... nhưng bạn không cần phải làm như vậy, trừ khi [khóa] chứa các ký tự nhất định (hoặc kết hợp các ký tự khiến nó trở thành từ khóa)"

Tôi thấy phần trước (một số ký tự nhất định) là đúng, sử dụng dấu @ (trên thực tế, tôi nghĩ $ và _ là các ký tự duy nhất không gây ra lỗi):

var a = {a@b:1};

=> Lỗi cú pháp

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

=> 1

nhưng dấu ngoặc đơn về từ khóa, như tôi đã trình bày ở trên, không đúng.

Những gì tôi muốn hoạt động vì văn bản giữa dấu mở đầu {và dấu hai chấm, hoặc giữa dấu phẩy và dấu hai chấm cho các thuộc tính tiếp theo được sử dụng như một chuỗi không được trích dẫn để tạo khóa đối tượng, hoặc, như Friedo đã nói, một tên biến ở đó không ' t được nội suy:

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

=> ABC123


-3

Nếu json mô tả các đối tượng, thì trong thực tế, bạn sẽ có những điều sau

var foo = {};

var bar = 1;

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

vậy thì,

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

vì vậy, ngay cả khi các ví dụ của bạn tạo ra cùng một kết quả, các ví dụ tương đương của chúng trong "mã thô" sẽ không. Có lẽ vì vậy mà ?? dunno, chỉ là một ý tưởng.


3
@David, tên biến không được nội suy trong JS khi được sử dụng làm khóa đối tượng. { bar: 'goodbye' }sẽ không đặt tên khóa thành giá trị của bar, nó sẽ chỉ là bar. Những người khác nói đúng về lý do tại sao đặc tả yêu cầu dấu ngoặc kép: đó là để tránh xung đột từ khóa và ký tự đặc biệt.
Friedo

-3

Nó có thể giảm kích thước dữ liệu nếu dấu ngoặc kép trên tên chỉ được phép khi cần thiết

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.