Merupakan null dalam JSON

423

Apa metode yang disukai untuk mengembalikan nilai nol di JSON? Apakah ada preferensi yang berbeda untuk primitif?

Misalnya, jika objek saya di server memiliki Integer yang disebut "myCount" tanpa nilai, JSON paling benar untuk nilai itu adalah:

{}

atau

{
    "myCount": null
}

atau

{
    "myCount": 0
}

Pertanyaan yang sama untuk Strings - jika saya memiliki string nol "myString" di server, adalah JSON terbaik:

{}

atau

{
    "myString": null
}

atau

{
    "myString": ""
}

atau (tuan bantu aku)

{
    "myString": "null"
}

Saya suka konvensi untuk koleksi diwakili di JSON sebagai koleksi kosong http://jtechies.blogspot.nl/2012/07/item-43-return-empty-arrays-or.html

Array kosong akan ditampilkan:

{
    "myArray": []
}

Ringkasan EDIT

Argumen 'preferensi pribadi' tampak realistis, tetapi kelihatannya tidak terlalu jelas, sebagai sebuah komunitas, kita akan mengkonsumsi lebih banyak layanan / sumber yang berbeda. Konvensi untuk struktur JSON akan membantu menormalkan konsumsi dan penggunaan kembali layanan tersebut. Sejauh menetapkan standar, saya akan menyarankan mengadopsi sebagian besar konvensi Jackson dengan beberapa pengecualian:

  • Objek lebih disukai daripada primitif.
  • Koleksi kosong lebih disukai daripada nol.
  • Objek tanpa nilai direpresentasikan sebagai null.
  • Primitif mengembalikan nilainya.

Jika Anda mengembalikan objek JSON dengan nilai sebagian besar nol, Anda mungkin memiliki kandidat untuk melakukan refactoring ke beberapa layanan.

{

    "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 di atas dihasilkan dari kelas Java berikut.

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()));
    }
}

Ketergantungan maven:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.3.0</version>
</dependency>
pherris
sumber
5
Tidak ada cara terbaik. Pilih apa yang paling mudah dikonsumsi untuk klien dalam kasus penggunaan konkret Anda. Dalam semangat mengembalikan koleksi kosong alih-alih null, pertimbangkan apakah klien Anda lebih baik menggunakan string kosong atau null- string yang berisi kata "null" tidak dapat dibedakan dari nilai yang valid, jangan lakukan itu.
Philipp Reichart
3
0 atau string kosong bisa saja memiliki arti berbeda dari nol, yang bisa memiliki arti berbeda dari atribut yang tidak ada. Jika Anda ingin mewakili nol, gunakan null. Itu yang paling eksplisit.
John Sheehan
Dalam Objective-C ada NSNullkelas yang didefinisikan yang memiliki instance tunggal. Referensi ke instance itu setara dengan JSON null. Saya kira bahasa lain bisa melakukan hal yang sama. Tentu saja, seseorang harus memeriksa kelas objek yang diterima sebelum melakukan casting ke kelas yang diduga - menjadi "null aware", seolah-olah.
Hot Licks
2
Perhatikan bahwa memiliki daftar "null" juga bukan praktik terbaik di Jawa: jika daftar tersebut diharapkan kosong, inisialisasikan ke daftar kosong. Jika diperlukan untuk tetap kosong (misalnya karena akan digantikan grosir dengan daftar baru daripada dimodifikasi untuk menambahkan nilai-nilai), menginisialisasinya ke dalam daftar kosong (yaitu Collections.emptyList()). Melakukan hal itu menghindari bug referensi nol yang dapat menyusahkan jika tidak.
Periata Breatta
@HotLicks - itu hanya mungkin karena Objective-C diketik secara dinamis. Di Java, misalnya, Anda tidak bisa memiliki kelas (berguna) Nullkarena Anda hanya akan dapat menetapkan nilainya ke objek dari tipe atau tipe sendiri Object.
Periata Breatta

Jawaban:

379

Mari kita evaluasi parsing masing-masing:

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: []}

The tl; dr sini:

Fragmen dalam variabel json2 adalah cara yang ditunjukkan oleh spesifikasi JSONnull . Tapi seperti biasa, itu tergantung pada apa yang Anda lakukan - kadang-kadang cara yang "benar" untuk melakukannya tidak selalu berhasil untuk situasi Anda. Gunakan penilaian Anda dan buat keputusan yang tepat.


JSON1 {}

Ini mengembalikan objek kosong. Tidak ada data di sana, dan itu hanya akan memberi tahu Anda bahwa kunci apa pun yang Anda cari (baik itu myCountatau sesuatu yang lain) adalah tipe undefined.


JSON2 {"myCount": null}

Dalam hal ini, myCountsebenarnya didefinisikan, meskipun nilainya null. Ini tidak sama dengan "tidak undefineddan tidak null", dan jika Anda menguji untuk satu kondisi atau yang lain, ini mungkin berhasil sedangkan JSON1 akan gagal.

Ini adalah cara definitif untuk mewakili nullper spesifikasi JSON .


JSON3 {"myCount": 0}

Dalam hal ini, myCount adalah 0. Itu tidak sama dengan null, dan itu tidak sama dengan false. Jika pernyataan bersyarat Anda mengevaluasi myCount > 0, maka ini mungkin bermanfaat untuk dimiliki. Selain itu, jika Anda menjalankan perhitungan berdasarkan nilai di sini, 0 bisa berguna. Namun, jika Anda mencoba menguji null, ini sebenarnya tidak akan berhasil sama sekali.


JSON4 {"myString": ""}

Dalam hal ini, Anda mendapatkan string kosong. Sekali lagi, seperti JSON2, itu didefinisikan, tetapi kosong. Anda dapat menguji if (obj.myString == "")tetapi Anda tidak dapat menguji nullatau undefined.


JSON5 {"myString": "null"}

Ini mungkin akan membuat Anda dalam masalah, karena Anda menetapkan nilai string ke nol; dalam hal ini, obj.myString == "null"bagaimanapun tidak == null .


JSON6 {"myArray": []}

Ini akan memberi tahu Anda bahwa array Anda myArrayada, tetapi kosong. Ini berguna jika Anda mencoba melakukan penghitungan atau evaluasi myArray. Misalnya, Anda ingin mengevaluasi jumlah foto yang diposkan pengguna - yang dapat Anda lakukan myArray.lengthdan akan kembali 0: ditentukan, tetapi tidak ada foto yang diposkan.

naskah merek
sumber
1
Terima kasih banyak, sangat membantu. Hanya simpul sisi kecil; ketika Play Json (scala) membuat cerita bersambung Opsi [String] = Tidak ada hasil JSON1yaitu{}
Neil
207

nullbukan nol. Ini bukan nilai, per se : itu adalah nilai di luar domain variabel yang menunjukkan data yang hilang atau tidak dikenal.

Hanya ada satu cara untuk mewakili nulldi JSON. Sesuai spesifikasi ( RFC 4627 dan json.org ):

2.1. Nilai-nilai

Nilai JSON HARUS berupa objek, array, angka, atau string, atau salah satunya
tiga nama literal berikut:

  false null true

masukkan deskripsi gambar di sini

Nicholas Carey
sumber
8
Sangat memalukan bahwa null harus hadir sama sekali. 4 karakter gratis. Pasti menyenangkan untuk hanya mengecualikan nilai sepenuhnya. json = '{"myValue":}';
Richard A Quadling
119
@Richard A Quadling - Saya seorang pengikut Hal Abelson "Program harus ditulis untuk dibaca orang, dan hanya untuk mesin yang dieksekusi". Saya lebih suka kata 'null', menegaskan niat programmer, dan bukan hanya masalah kelalaian yang tidak disengaja.
Scott Smith
13
@ Dave Mei: "Nilai JSON bukan program" - Maksud saya adalah tentang maksud pensinyalan dengan cara yang tidak ambigu. Ya, biayanya empat karakter tambahan, dan untuk beberapa aplikasi perbedaannya mungkin signifikan. Namun dalam banyak kasus, manfaat dari membuat kesalahan terlihat jauh melebihi manfaat dari optimasi kecil.
Scott Smith
11
@Dave Juga, menurut json.org, JSON "mudah bagi manusia untuk membaca dan menulis."
Sophivorus
14
Juga perhatikan bahwa jika Anda memiliki masalah dengan 4 karakter ASCII, JSON bukan pendekatan terbaik, lihat Binary JSON atau lebih baik ke format biner murni.
PhoneixS
26

Hanya ada satu cara untuk mewakili null; itu dengan 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

Artinya; jika ada klien yang menggunakan representasi JSON Anda menggunakan ===operator; itu bisa menjadi masalah bagi mereka.

Tidak bernilai

Jika Anda ingin menyampaikan bahwa Anda memiliki objek yang atributnya myCounttidak memiliki nilai:

{ "myCount": null }

tidak ada atribut / atribut yang hilang

Bagaimana jika Anda menyampaikan bahwa Anda memiliki objek tanpa atribut:

{}

Kode klien akan mencoba mengakses myCountdan mendapatkan undefined; itu tidak ada di sana.

koleksi kosong

Bagaimana jika Anda menyampaikan bahwa Anda memiliki objek dengan atribut myCountyang merupakan daftar kosong:

{ "myCount": [] }
tidak tahu
sumber
Memberi +1 contoh yang baik dengan perbandingan, tetapi akan membantu untuk membedakan antara javascript dan json, yang berarti, representasi null dalam javascript tidak harus cocok dengan json (walaupun itu memang).
Mladen B.
15

Saya akan gunakan nulluntuk menunjukkan bahwa tidak ada nilai untuk kunci khusus itu. Misalnya, gunakan nulluntuk menyatakan bahwa "jumlah perangkat di rumah Anda terhubung ke internet" tidak diketahui.

Di sisi lain, gunakan {}jika kunci tertentu itu tidak berlaku. Misalnya, Anda tidak boleh menunjukkan hitungan, bahkan jika null, untuk pertanyaan "jumlah mobil yang memiliki koneksi internet aktif" diminta kepada seseorang yang tidak memiliki mobil.

Saya akan menghindari default nilai apa pun kecuali default itu masuk akal. Meskipun Anda mungkin memutuskan untuk menggunakan nulluntuk mewakili tidak ada nilai, tentu tidak pernah digunakan "null"untuk melakukannya.

marcoseu
sumber
7

Saya akan memilih "default" untuk tipe data variabel ( nulluntuk string / objek, 0untuk angka), tetapi memang memeriksa kode apa yang akan mengkonsumsi objek yang diharapkan. Jangan lupa ada kadang-kadang ada perbedaan antara null/ default vs "not present".

Lihat pola objek nol - terkadang lebih baik untuk melewatkan beberapa objek khusus daripada null(misalnya []array daripada nulluntuk array atau ""untuk string).

Alexei Levenkov
sumber
2

Ini adalah pilihan pribadi dan situasional. Yang penting untuk diingat adalah bahwa string kosong dan angka nol secara konseptual berbeda null.

Dalam kasus a, countAnda mungkin selalu menginginkan angka yang valid (kecuali jika counttidak diketahui atau tidak terdefinisi), tetapi dalam kasus string, siapa yang tahu? String kosong dapat berarti sesuatu dalam aplikasi Anda. Atau mungkin tidak. Terserah Anda yang memutuskan.

Wayne
sumber
1

Menurut spesifikasi JSON , wadah terluar tidak harus berupa kamus (atau 'objek') sebagaimana tersirat dalam sebagian besar komentar di atas. Ini juga bisa berupa daftar atau nilai telanjang (yaitu string, angka, boolean atau null). Jika Anda ingin mewakili nilai nol di JSON, seluruh string JSON (tidak termasuk tanda kutip yang berisi string JSON) adalah sederhana null. Tanpa kawat gigi, tidak ada kurung, tidak ada tanda kutip. Anda dapat menentukan kamus yang berisi kunci dengan nilai nol ( {"key1":null}), atau daftar dengan nilai nol ( [null]), tetapi ini bukan nilai nol sendiri - kamus dan daftar yang tepat. Demikian pula, kamus kosong ( {}) atau daftar kosong ( []) baik-baik saja, tetapi juga tidak nol.

Dengan 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
iggie
sumber
Perhatikan bahwa tata bahasa Formulir McKeeman di bilah sisi kanan halaman spesifikasi JSON tertaut yang memvalidasi pernyataan bahwa bare nullmerupakan JSON yang valid. Teks tubuh utama dan ilustrasi di sana tidak jelas dan jika ada yang menyarankan hanya objek dan array yang valid pada root.
yoyoyoyosef