Đại diện cho null trong JSON


422

Phương thức ưa thích để trả về các giá trị null trong JSON là gì? Có một ưu tiên khác nhau cho người nguyên thủy?

Ví dụ: nếu đối tượng của tôi trên máy chủ có một Số nguyên gọi là "myCount" không có giá trị, thì JSON chính xác nhất cho giá trị đó sẽ là:

{}

hoặc là

{
    "myCount": null
}

hoặc là

{
    "myCount": 0
}

Câu hỏi tương tự cho Chuỗi - nếu tôi có chuỗi null "myString" trên máy chủ, là JSON tốt nhất:

{}

hoặc là

{
    "myString": null
}

hoặc là

{
    "myString": ""
}

hoặc (chúa giúp tôi)

{
    "myString": "null"
}

Tôi thích quy ước cho các bộ sưu tập được thể hiện trong JSON dưới dạng một bộ sưu tập trống http://jtechies.blogspot.nl/2012/07/item-43-return-empty-arrays-or.html

Một mảng trống sẽ được trình bày:

{
    "myArray": []
}

Tóm tắt EDIT

Đối số 'sở thích cá nhân' có vẻ thực tế, nhưng thiển cận ở chỗ, vì là một cộng đồng, chúng ta sẽ tiêu thụ một số lượng lớn hơn các dịch vụ / nguồn khác nhau. Các quy ước về cấu trúc JSON sẽ giúp bình thường hóa việc tiêu thụ và tái sử dụng các dịch vụ nói trên. Theo như thiết lập một tiêu chuẩn, tôi sẽ đề nghị áp dụng hầu hết các công ước của Jackson với một vài ngoại lệ:

  • Đối tượng được ưa thích hơn so với nguyên thủy.
  • Bộ sưu tập trống được ưa thích hơn null.
  • Các đối tượng không có giá trị được biểu diễn dưới dạng null.
  • Người nguyên thủy trả lại giá trị của họ.

Nếu bạn đang trả về một đối tượng JSON có giá trị hầu hết là null, bạn có thể có một ứng cử viên để tái cấu trúc thành nhiều dịch vụ.

{

    "value1": null,

    "value2": null,

    "text1": null,

    "text2": "hello",

    "intValue": 0, //use primitive only if you are absolutely sure the answer is 0

    "myList": [],

    "myEmptyList": null, //NOT BEST PRACTICE - return [] instead

    "boolean1": null, //use primitive only if you are absolutely sure the answer is true/false

    "littleboolean": false

}

JSON ở trên được tạo từ lớp Java sau.

package jackson;

import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonApp {

    public static class Data {

        public Integer value1;

        public Integer value2;

        public String text1;

        public String text2 = "hello";

        public int intValue;

        public List<Object> myList = new ArrayList<Object>();

        public List<Object> myEmptyList;

        public Boolean boolean1;

        public boolean littleboolean;

    }

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.writeValueAsString(new Data()));
    }
}

Phụ thuộc Maven:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.3.0</version>
</dependency>

5
Không có cách nào tốt nhất. Chọn những gì dễ tiêu thụ nhất cho khách hàng trong trường hợp sử dụng cụ thể của bạn. Với tinh thần trả lại các bộ sưu tập trống thay vì null, hãy xem xét liệu khách hàng của bạn có tốt hơn với chuỗi trống hay null- một chuỗi chứa từ "null" không thể phân biệt được với một giá trị hợp lệ, đừng làm điều đó.
Philipp Reichart

3
0 hoặc một chuỗi rỗng rất có thể có ý nghĩa khác với null, có thể có ý nghĩa khác với thuộc tính không tồn tại. Nếu bạn muốn đại diện cho null, sử dụng null. Đó là rõ ràng nhất.
John Sheehan

Trong Objective-C có một NSNulllớp được xác định có một cá thể đơn lẻ. Một tham chiếu đến thể hiện đó tương đương với JSON null. Tôi đoán rằng một ngôn ngữ khác có thể làm điều tương tự. Tất nhiên, người ta sẽ phải kiểm tra lớp của đối tượng nhận được trước khi chuyển sang lớp được giả định - là "không biết", như vậy.
Licks nóng

2
Lưu ý rằng việc có một danh sách "null" cũng không phải là cách thực hành tốt nhất trong Java: nếu danh sách dự kiến ​​sẽ trống, hãy khởi tạo nó thành một danh sách trống. Nếu nó là cần thiết để duy trì sản phẩm nào (ví dụ vì nó sẽ được thay thế bằng bán buôn một danh sách mới chứ không phải là sửa đổi để thêm giá trị), khởi nó đến các danh sách trống (ví dụ Collections.emptyList()). Làm như vậy để tránh các lỗi tham chiếu null có thể là một nỗi đau khác.
Periata Breatta

@HotLicks - Điều đó chỉ khả thi vì Objective-C được gõ động. Ví dụ, trong Java, bạn không thể có một Nulllớp (hữu ích) vì bạn chỉ có thể gán các giá trị của nó cho các đối tượng thuộc loại hoặc kiểu riêng của nó Object.
Periata Breatta

Câu trả lời:


378

Hãy đánh giá phân tích từng cái:

http://jsfiddle.net/brandonscript/Y2dGv/

var json1 = '{}';
var json2 = '{"myCount": null}';
var json3 = '{"myCount": 0}';
var json4 = '{"myString": ""}';
var json5 = '{"myString": "null"}';
var json6 = '{"myArray": []}';

console.log(JSON.parse(json1)); // {}
console.log(JSON.parse(json2)); // {myCount: null}
console.log(JSON.parse(json3)); // {myCount: 0}
console.log(JSON.parse(json4)); // {myString: ""}
console.log(JSON.parse(json5)); // {myString: "null"}
console.log(JSON.parse(json6)); // {myArray: []}

Các tl; dr ở đây:

Đoạn trong biến json2 là cách biểu thị thông số JSON chỉ ra null. Nhưng như mọi khi, nó phụ thuộc vào những gì bạn đang làm - đôi khi cách "đúng" để làm điều đó không phải lúc nào cũng phù hợp với tình huống của bạn. Sử dụng phán đoán của bạn và đưa ra quyết định sáng suốt.


JSON1 {}

Điều này trả về một đối tượng trống. Không có dữ liệu ở đó, và nó sẽ chỉ cho bạn biết rằng bất kỳ khóa nào bạn đang tìm kiếm (có thể là myCountmột cái gì đó khác) là loại undefined.


JSON2 {"myCount": null}

Trong trường hợp này, myCountthực sự được xác định, mặc dù giá trị của nó là null. Điều này không giống với cả "không undefinedvà không null" và nếu bạn đang thử nghiệm điều kiện này hay điều kiện khác, điều này có thể thành công trong khi JSON1 sẽ thất bại.

Đây là cách dứt khoát để thể hiện nulltheo thông số JSON .


JSON3 {"myCount": 0}

Trong trường hợp này, myCount là 0. Điều đó không giống nullvà, nó không giống như false. Nếu tuyên bố điều kiện của bạn đánh giá myCount > 0, thì điều này có thể đáng để có. Hơn nữa, nếu bạn đang chạy các tính toán dựa trên giá trị ở đây, 0 có thể hữu ích. Nếu bạn đang cố gắng kiểm tra nulltuy nhiên, điều này thực sự sẽ không hoạt động.


JSON4 {"myString": ""}

Trong trường hợp này, bạn đang nhận được một chuỗi rỗng. Một lần nữa, như với JSON2, nó được định nghĩa, nhưng nó trống rỗng. Bạn có thể kiểm tra if (obj.myString == "")nhưng bạn không thể kiểm tra nullhoặc undefined.


JSON5 {"myString": "null"}

Điều này có thể sẽ khiến bạn gặp rắc rối, vì bạn đang đặt giá trị chuỗi thành null; trong trường hợp này, obj.myString == "null"tuy nhiên không phải vậy == null .


JSON6 {"myArray": []}

Điều này sẽ cho bạn biết rằng mảng của bạn myArraytồn tại, nhưng nó trống rỗng. Điều này hữu ích nếu bạn đang cố gắng thực hiện đếm hoặc đánh giá myArray. Chẳng hạn, giả sử bạn muốn đánh giá số lượng ảnh người dùng đã đăng - bạn có thể làm myArray.lengthvà nó sẽ trả về 0: được xác định, nhưng không có ảnh nào được đăng.


1
Cảm ơn rất nhiều, rất hữu ích. Chỉ là một nút bên nhỏ; khi Play Json (scala) tuần tự hóa Tùy chọn [Chuỗi] = Không có kết quả nào JSON1tức là{}
Neil

207

nullkhông phải là không. Nó không phải là một giá trị, mỗi se : nó là một giá trị bên ngoài miền của biến chỉ ra dữ liệu bị thiếu hoặc không xác định.

Chỉ có một cách để biểu diễn nulltrong JSON. Theo thông số kỹ thuật ( RFC 4627json.org ):

2.1. Giá trị

Giá trị JSON PHẢI là một đối tượng, mảng, số hoặc chuỗi hoặc một trong
ba tên theo nghĩa đen sau đây:

  sai null đúng

nhập mô tả hình ảnh ở đây


8
Thật là xấu hổ khi null phải có mặt ở tất cả. 4 ký tự không có gì. Nó đã được tốt đẹp chỉ đơn giản là loại trừ hoàn toàn giá trị. json = '{"myValue":}';
Richard A Quadling

119
@Richard Một Quadling - Tôi là người theo dõi "Các chương trình phải được viết cho mọi người đọc và chỉ tình cờ cho máy thực thi". Tôi thích từ 'null', xác nhận ý định của lập trình viên, và không chỉ là một câu hỏi về sự thiếu sót tình cờ.
Scott Smith

13
@Dave May: "Giá trị JSON không phải là chương trình" - Quan điểm của tôi là về ý định báo hiệu một cách rõ ràng. Có, chi phí thêm bốn ký tự và đối với một số ứng dụng, sự khác biệt có thể là đáng kể. Tuy nhiên, trong nhiều trường hợp, lợi ích của việc tạo ra lỗi trông có vẻ vượt xa lợi ích của việc tối ưu hóa nhỏ.
Scott Smith

11
@Dave Ngoài ra, theo json.org, JSON "dễ dàng cho con người đọc và viết."
Sophivorus

14
Cũng lưu ý rằng nếu bạn gặp vấn đề với 4 ký tự ASCII, JSON không phải là cách tiếp cận tốt nhất, hãy xem Binary JSON hoặc tốt hơn là định dạng nhị phân thuần túy.
PhoneixS

26

Chỉ có một cách để đại diện null; đó là với null.

console.log(null === null);   // true
console.log(null === true);   // false
console.log(null === false);  // false
console.log(null === 'null'); // false
console.log(null === "null"); // false
console.log(null === "");     // false
console.log(null === []);     // false
console.log(null === 0);      // false

Điều đó có nghĩa là; nếu bất kỳ ứng dụng khách nào sử dụng biểu diễn JSON của bạn sử dụng ===toán tử; nó có thể là một vấn đề cho họ

không có giá trị

Nếu bạn muốn truyền đạt rằng bạn có một đối tượng có thuộc tính myCountkhông có giá trị:

{ "myCount": null }

không có thuộc tính / thuộc tính bị thiếu

Điều gì sẽ xảy ra nếu bạn truyền đạt rằng bạn có một đối tượng không có thuộc tính:

{}

Mã khách hàng sẽ cố gắng truy cập myCountvà nhận undefined; nó không có ở đó

bộ sưu tập trống

Điều gì sẽ xảy ra nếu bạn truyền đạt rằng bạn có một đối tượng với thuộc tính myCountlà danh sách trống:

{ "myCount": [] }

+1 ví dụ tốt với so sánh, nhưng sẽ hữu ích khi phân biệt giữa javascript và json, nghĩa là, đại diện của null trong javascript không phải khớp với json (mặc dù vậy).
Mladen B.

15

Tôi sẽ sử dụng nullđể chỉ ra rằng không có giá trị cho khóa cụ thể đó. Ví dụ: sử dụng nullđể thể hiện rằng "số thiết bị trong gia đình bạn kết nối với internet" là không xác định.

Mặt khác, sử dụng {}nếu khóa cụ thể đó không được áp dụng. Ví dụ: bạn không nên hiển thị số đếm, ngay cả khi nullcâu hỏi "số xe có kết nối internet đang hoạt động" được hỏi cho người không sở hữu bất kỳ chiếc xe nào.

Tôi sẽ tránh mặc định bất kỳ giá trị nào trừ khi mặc định đó có ý nghĩa. Mặc dù bạn có thể quyết định sử dụng nullđể thể hiện không có giá trị, nhưng chắc chắn không bao giờ sử dụng "null"để làm như vậy.


7

Tôi sẽ chọn "mặc định" cho loại dữ liệu của biến ( nullcho chuỗi / đối tượng, 0cho số), nhưng thực sự kiểm tra mã nào sẽ tiêu thụ đối tượng mong đợi. Đừng quên đôi khi có sự phân biệt giữa null/ mặc định so với "không có mặt".

Kiểm tra mẫu đối tượng null - đôi khi tốt hơn là truyền một số đối tượng đặc biệt thay vì null(tức là []mảng thay vì nullcho mảng hoặc ""cho chuỗi).


2

Đây là một lựa chọn cá nhân và tình huống. Điều quan trọng cần nhớ là chuỗi rỗng và số 0 khác biệt về mặt khái niệm null.

Trong trường hợp countcó lẽ bạn luôn muốn có một số hợp lệ (trừ khi countkhông xác định hoặc không xác định), nhưng trong trường hợp chuỗi, ai biết? Chuỗi rỗng có thể có nghĩa là một cái gì đó trong ứng dụng của bạn. Hoặc có thể nó không. Đó là do bạn quyết định.


1

Theo thông số JSON , thùng chứa ngoài cùng không phải là một từ điển (hoặc 'đối tượng') như được ngụ ý trong hầu hết các ý kiến ​​trên. Nó cũng có thể là một danh sách hoặc một giá trị trần (ví dụ: chuỗi, số, boolean hoặc null). Nếu bạn muốn biểu thị một giá trị null trong JSON, toàn bộ chuỗi JSON (không bao gồm các trích dẫn có chứa chuỗi JSON) chỉ đơn giản là null. Không niềng răng, không dấu ngoặc, không dấu ngoặc kép. Bạn có thể chỉ định một từ điển chứa khóa có giá trị null ( {"key1":null}) hoặc danh sách có giá trị null ( [null]), nhưng đây không phải là giá trị null - chúng là từ điển và danh sách phù hợp. Tương tự, một từ điển trống ( {}) hoặc một danh sách trống ( []) hoàn toàn tốt, nhưng cũng không có giá trị.

Trong Python:

>>> print json.loads('{"key1":null}')
{u'key1': None}
>>> print json.loads('[null]')
[None]
>>> print json.loads('[]')
[]
>>> print json.loads('{}')
{}
>>> print json.loads('null')
None

Lưu ý rằng đó là ngữ pháp của McKeeman Form trên thanh bên phải của trang đặc tả JSON được liên kết để xác nhận xác nhận rằng trần nulltạo thành JSON hợp lệ. Văn bản chính và hình minh họa có mơ hồ và nếu bất cứ điều gì dường như chỉ đề xuất các đối tượng và mảng là hợp lệ ở gốc.
yoyoyoyosef
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.