JSON hợp lệ tối thiểu là gì?


174

Tôi đã đọc kỹ mô tả JSON http://json.org/ nhưng tôi không chắc mình biết câu trả lời cho câu hỏi đơn giản. Những chuỗi nào là JSON hợp lệ tối thiểu có thể có?

  • "string" chuỗi JSON hợp lệ?
  • 42 số JSON đơn giản có hợp lệ không?
  • true giá trị boolean là JSON hợp lệ?
  • {} đối tượng trống là một JSON hợp lệ?
  • [] mảng trống có phải là JSON hợp lệ không?

12
Thử nghiệm tại jsonlint.com , hai cái cuối cùng là hợp lệ, những cái khác thì không.
ironcito

1
một số trình phân tích cú pháp JSON mong đợi một mảng hoặc một đối tượng. Họ phàn nàn về chỉ một số, hoặc một chuỗi.
akonsu

3
Đến bây giờ, những thứ đó là hợp lệ
Brian Colavito


câu trả lời ngắn gọn - {}
Tukaram Bhosale

Câu trả lời:


156

Tại thời điểm viết bài, JSON chỉ được mô tả trong RFC4627 . Nó mô tả (ở đầu "2") một văn bản JSON là một đối tượng hoặc mảng được tuần tự hóa.

Điều này có nghĩa là chỉ {}[]là các chuỗi JSON hoàn chỉnh, hợp lệ trong các trình phân tích cú pháp và chuỗi ký tự tuân thủ tiêu chuẩn đó.

Tuy nhiên , việc giới thiệu ECMA-404 thay đổi điều đó và lời khuyên cập nhật có thể được đọc tại đây . Tôi cũng đã viết một bài blog về vấn đề này.


Tuy nhiên, để gây nhầm lẫn hơn nữa, JSONđối tượng (ví dụ JSON.parse()JSON.stringify()) có sẵn trong trình duyệt web được tiêu chuẩn hóa trong ES5 và điều đó xác định rõ các văn bản JSON có thể chấp nhận như vậy:

Định dạng trao đổi JSON được sử dụng trong đặc tả này chính xác được mô tả bởi RFC 4627 với hai ngoại lệ:

  • Việc sản xuất JSONText cấp cao nhất của ngữ pháp JSON của ECMAScript có thể bao gồm bất kỳ JSONValue nào thay vì bị giới hạn là JSONObject hoặc JSONArray như được chỉ định bởi RFC 4627.

  • bắn tỉa

Điều này có nghĩa là tất cả các giá trị JSON (bao gồm chuỗi, null và số) được đối tượng JSON chấp nhận, mặc dù đối tượng JSON tuân thủ kỹ thuật RFC 4627.

Lưu ý rằng do đó bạn có thể xâu chuỗi một số trong trình duyệt phù hợp thông qua JSON.stringify(5), trình duyệt này sẽ bị từ chối bởi một trình phân tích cú pháp khác tuân thủ RFC4627, nhưng không có ngoại lệ cụ thể được liệt kê ở trên. Ruby, ví dụ, dường như là một ví dụ như vậy chỉ chấp nhận các đối tượng và mảng là gốc . Mặt khác, PHP đặc biệt bổ sung ngoại lệ rằng "nó cũng sẽ mã hóa và giải mã các loại vô hướng và NULL".


@amdorra: Bạn có thể cụ thể hơn khi bạn nhìn thấy điều đó không?
Matt

5
JSON không phải là một danh từ, vì vậy "JSON" là vô nghĩa. Bất kỳ "giá trị JSON" nào cũng là "giá trị JSON", nhưng các trình phân tích cú pháp thường mong đợi "văn bản JSON" như được định nghĩa trong RFC đó.
IMSoP

2
xấu của tôi, tôi sẽ xóa câu trả lời của tôi sau đó
amdorra

1
@jmoreno Bạn có thể vui lòng làm rõ nhận xét của bạn? Bạn đang nói true, falsehoặc nullmột mình là một văn bản JSON hợp lệ? Bạn có thể vui lòng trích dẫn một nguồn, vì điều này mâu thuẫn với hầu hết các câu trả lời / nhận xét khác ở đây?
Lawrence Johnston

2
@jmoreno: Chắc chắn là trích dẫn từ phần 2 "Một văn bản JSON là một đối tượng hoặc mảng được tuần tự hóa." Phản đối điều đó? JSON Lint cũng không nghĩ rằng một mảng hoặc đối tượng không hợp lệ. Không có tranh luận về việc một chuỗi có phải là một chữ JSON hợp lệ hay không; điều này là kết thúc nếu một chuỗi tự nó là hợp lệ.
Matt

42

Có ít nhất bốn tài liệu có thể được coi là tiêu chuẩn JSON trên Internet. Các RFC tham chiếu tất cả mô tả loại mime application/json. Dưới đây là những gì mỗi người nói về các giá trị cấp cao nhất và liệu có bất kỳ thứ gì ngoài đối tượng hoặc mảng được cho phép ở trên cùng không:

RFC-4627 : Không.

Một văn bản JSON là một chuỗi các mã thông báo. Bộ mã thông báo bao gồm sáu ký tự cấu trúc, chuỗi, số và ba tên bằng chữ.

Một văn bản JSON là một đối tượng hoặc mảng được tuần tự hóa.

JSON-text = object / mảng

Lưu ý rằng RFC-4627 được đánh dấu là "thông tin" trái ngược với "tiêu chuẩn đề xuất" và nó bị lỗi bởi RFC-7159 , do đó RFC-8259 đã bị lỗi thời.

RFC-8259 : Có.

Một văn bản JSON là một chuỗi các mã thông báo. Bộ mã thông báo bao gồm sáu ký tự cấu trúc, chuỗi, số và ba tên bằng chữ.

Một văn bản JSON là một giá trị nối tiếp. Lưu ý rằng một số thông số kỹ thuật trước đây của JSON đã ràng buộc một văn bản JSON là một đối tượng hoặc một mảng. Các triển khai chỉ tạo các đối tượng hoặc mảng trong đó một văn bản JSON được gọi sẽ tương thích với nhau theo nghĩa là tất cả các triển khai sẽ chấp nhận chúng như các văn bản JSON tuân thủ.

JSON-text = ws value ws

RFC-8259 là ngày tháng 12 năm 2017 và được đánh dấu là "TIÊU CHUẨN INTERNET".

ECMA-262 : Có.

Ngữ pháp cú pháp JSON định nghĩa một văn bản JSON hợp lệ theo các mã thông báo được xác định bởi ngữ pháp từ vựng JSON. Biểu tượng mục tiêu của ngữ pháp là JSONText.

Cú pháp cú pháp:

JSONValue

JSONValue:

JSONNullLiteral

JSONBooleanLiteral

JSONObject

Mã độc

JSONString

Số liệu

ECMA-404 : Có.

Văn bản JSON là một chuỗi các mã thông báo được hình thành từ các điểm mã Unicode phù hợp với ngữ pháp giá trị JSON. Bộ mã thông báo bao gồm sáu mã thông báo cấu trúc, chuỗi, số và ba mã thông báo tên theo nghĩa đen.


10

Theo định nghĩa cũ trong RFC 4627 (đã bị lỗi thời vào tháng 3 năm 2014 bởi RFC 7159), tất cả đều là "giá trị JSON" hợp lệ, nhưng chỉ hai cái cuối cùng sẽ tạo thành một "văn bản JSON" hoàn chỉnh:

Một văn bản JSON là một đối tượng hoặc mảng được tuần tự hóa.

Tùy thuộc vào trình phân tích cú pháp được sử dụng, "giá trị JSON" đơn độc có thể được chấp nhận bằng mọi cách. Ví dụ: (bám sát thuật ngữ "giá trị JSON" so với thuật ngữ "văn bản JSON"):

  • các JSON.parse()chức năng hiện nay tiêu chuẩn trong các trình duyệt hiện đại chấp nhận bất kỳ "JSON giá trị"
  • hàm PHP json_decodeđược giới thiệu trong phiên bản 5.2.0 chỉ chấp nhận toàn bộ "văn bản JSON", nhưng đã được sửa đổi để chấp nhận bất kỳ "giá trị JSON" nào trong phiên bản 5.2.1
  • Python json.loadschấp nhận bất kỳ "giá trị JSON" nào theo các ví dụ trên trang hướng dẫn này
  • trình xác nhận tại http://jsonlint.com mong đợi một "văn bản JSON" đầy đủ
  • mô-đun Ruby JSON sẽ chỉ chấp nhận một "văn bản JSON" đầy đủ (ít nhất là theo các nhận xét trên trang hướng dẫn này )

Sự khác biệt giống như sự khác biệt giữa "tài liệu XML" và "đoạn XML", mặc dù về mặt kỹ thuật <foo />là một tài liệu XML được định dạng tốt (nó sẽ được viết tốt hơn <?xml version="1.0" ?><foo />, nhưng như đã nêu trong các nhận xét, <?xmltuyên bố là tùy chọn về mặt kỹ thuật ).


So sánh XML có thể không phù hợp, vì một tài liệu XML hoàn toàn hợp lệ mà không cần khai báo XML tùy chọn. Xem đề xuất XML tại w3.org/TR/xml/#sec-well-formed
Gunther

@Gunther Ah, vâng, tôi đã quên rằng đó là tùy chọn về mặt kỹ thuật, mặc dù rất được khuyến khích.
IMSoP

@Gunther: Một nitpick: <foo />là một tài liệu XML được định dạng tốt, nhưng không phải là một tài liệu hợp lệ . (Nhưng điều tương tự cũng đúng với <?xml version="1.0" ?><foo />.)
ruakh

@ruakh Thật thú vị, định nghĩa ở đây ngụ ý XML chỉ có thể là "hợp lệ" đối với DTD, có nghĩa là rất ít tài liệu XML, vì các DTD rất hiếm khi được viết và khai báo trong thực tế (so với các định dạng định nghĩa lược đồ như XSD hoặc RelaxNG) . Tôi đã kiểm tra, bởi vì nếu bạn có thể hợp lệ đối với một lược đồ bên ngoài, mà không tham chiếu đến nó, thì <foo /> có thể hoặc không thể hợp lệ đối với một lược đồ cụ thể , nhưng đó không phải là trạng thái tiêu chuẩn đó.
IMSoP

4

Đặc tả ecma có thể hữu ích để tham khảo:

http: //www.ecma-i Intl.org/ecma-262/5.1/

Hàm phân tích cú pháp phân tích một văn bản JSON (Chuỗi có định dạng JSON) và tạo ra giá trị ECMAScript. Định dạng JSON là một dạng hạn chế của chữ ECMAScript. Các đối tượng JSON được nhận ra dưới dạng các đối tượng ECMAScript. Mảng JSON được nhận ra là mảng ECMAScript. Chuỗi JSON, số, booleans và null được nhận ra dưới dạng Chuỗi ECMAScript, Numbers, Booleans và null. JSON sử dụng một bộ ký tự khoảng trắng hạn chế hơn WhiteSpace và cho phép các điểm mã Unicode U + 2028 và U + 2029 xuất hiện trực tiếp trong các chữ JSONString mà không cần sử dụng chuỗi thoát. Quá trình phân tích cú pháp tương tự như 11.1.4 và 11.1.5 bị ràng buộc bởi ngữ pháp JSON.

JSON.parse("string"); // SyntaxError: Unexpected token s
JSON.parse(43); // 43
JSON.parse("43"); // 43
JSON.parse(true); // true
JSON.parse("true"); // true
JSON.parse(false);
JSON.parse("false");
JSON.parse("trueee"); // SyntaxError: Unexpected token e
JSON.parse("{}"); // {}
JSON.parse("[]"); // []

4
Mặc dù là một tài liệu tham khảo hữu ích, đó là đặc điểm kỹ thuật của một trình phân tích cú pháp JSON cụ thể (cái được định nghĩa trong tiêu chuẩn ECMAScript) không dành cho định dạng. json.org tuyên bố rõ ràng rằng JSON "hoàn toàn độc lập với ngôn ngữ", do đó không có một trình phân tích cú pháp chính xác nào.
IMSoP

1
JavaScript / ECMAScipt là nguồn cảm hứng cho JSON và là người dùng của nó, nhưng không phải là "ngôi nhà" của nó. JSON được lấy từ ký hiệu nghĩa đen của đối tượng trong (tất cả các phiên bản trước đó của) ECMAScript, nhưng không giống với nó. Sau đó, JSON.parsechức năng này đã được thêm vào các phiên bản sau của tiêu chuẩn ECMAScript dựa trên ngữ pháp của Crockford và RFC.
IMSoP

4
Bạn nên làmJSON.parse("\"string\"");
ericbn

4

JSON là viết tắt của ký hiệu đối tượng JavaScript. Chỉ {}[]xác định một đối tượng Javascript. Các ví dụ khác là giá trị chữ. Có các loại đối tượng trong Javascript để làm việc với các giá trị đó, nhưng biểu thức "string"là biểu diễn mã nguồn của một giá trị bằng chữ và không phải là một đối tượng.

Hãy nhớ rằng JSON không phải là Javascript. Đó là một ký hiệu đại diện cho dữ liệu. Nó có một cấu trúc rất đơn giản và hạn chế. Dữ liệu JSON được cấu trúc bằng các {},:[]ký tự. Bạn chỉ có thể sử dụng các giá trị theo nghĩa đen bên trong cấu trúc đó.

Nó hoàn toàn hợp lệ khi một máy chủ phản hồi với mô tả đối tượng hoặc giá trị bằng chữ. Tất cả các trình phân tích cú pháp JSON nên được xử lý để chỉ xử lý một giá trị bằng chữ, nhưng chỉ một giá trị. JSON chỉ có thể đại diện cho một đối tượng tại một thời điểm. Vì vậy, để một máy chủ trả về nhiều hơn một giá trị, nó sẽ phải cấu trúc nó như một đối tượng hoặc một mảng.


1
Tôi nghĩ rằng việc tiếp cận câu trả lời từ hướng này nhiều hơn là làm rõ: nguồn gốc của tên không có liên quan đến các chi tiết của tiêu chuẩn và các loại có sẵn trong JavaScript có thể là nguồn cảm hứng cho các loại trong JSON, nhưng không có yêu cầu nào mà họ phù hợp. Phần giới thiệu trên json.org cho thấy rõ điều này: "JSON là một định dạng văn bản hoàn toàn độc lập với ngôn ngữ"
IMSoP

@IMSoP Tôi hoàn toàn đồng ý. Tôi đã trộn các loại Javascript với JSON và điều đó không đúng. Tôi sẽ cập nhật câu trả lời của tôi.
Phản ứng

2

Vâng, vâng, vâng, vâng, vâng. Tất cả chúng đều là giá trị JSON hợp lệ.

Tuy nhiên, RFC 4627 chính thức tuyên bố:

Một văn bản JSON là một đối tượng hoặc mảng được tuần tự hóa.

Vì vậy, toàn bộ "tập tin" phải bao gồm một đối tượng hoặc mảng là cấu trúc ngoài cùng, tất nhiên có thể trống. Tuy nhiên, nhiều trình phân tích cú pháp JSON cũng chấp nhận các giá trị nguyên thủy cho đầu vào.


-1
var x;
JSON.stringify(x); // will output "{}"

Vì vậy, câu trả lời của bạn là "{}"biểu thị một đối tượng trống.


FWIW, trong Chrome, điều này mang lại undefined, không phải là "{}" `
Matt

-2

Chỉ cần làm theo sơ đồ đường sắt được đưa ra trên trang json.org . [] và {} là các đối tượng JSON hợp lệ tối thiểu có thể. Vì vậy, câu trả lời là [] và {}.


3
Đó không phải là một FSM, đó là một ngữ pháp. Và nó dường như không chỉ ra sản xuất nào là quy tắc bắt đầu. Nếu các quy tắc bắt đầu là arrayobjectbạn sẽ đúng, nhưng nó hợp lý để mong đợi valuelà bắt đầu.

Trông khá đơn giản với tôi mặc dù. Douglas Crockford gọi họ như vậy và chúng tôi luôn bắt đầu từ bên trái và theo dấu vết bên phải. Bản nhạc nhỏ nhất cung cấp JSON hợp lệ tối thiểu.
Hrishi

2
Đó không phải là cách giải thích của bạn về bất kỳ quy tắc ngữ pháp cụ thể nào mà tôi phản đối, đó là bạn đã chọn hai quy tắc và cho rằng một quy tắc chỉ có thể bắt đầu từ những quy tắc đó, không phải từ những quy tắc khác. Nếu bạn nhìn vào valuesquy tắc thay vào đó (hoặc ngoài) quy tắc arrayobjectquy tắc, thì số và chuỗi độc lập là một tài liệu JSON hợp lệ.

-1. Thứ nhất, như @delnan chỉ ra, không có gì trong các sơ đồ tại json.org cho thấy rằng một văn bản JSON đầy đủ phải là một đối tượng hoặc mảng; bạn đã chọn hai cái đó một cách tùy tiện, không dựa trên bất cứ điều gì trên json.org. Thứ hai, nitpicking qua thuật ngữ : [], trong khi một văn bản JSON hợp lệ theo mọi thông số từng có ý kiến ​​về vấn đề này, không phải là "đối tượng JSON hợp lệ", vì nó không phải là đối tượng JSON. "Đối tượng" trong JSON đề cập cụ thể đến {}ký hiệu; Mảng JSON không phải là đối tượng JSON.
Đánh dấu Amery
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.