Katakanlah kita memiliki objek yang kompleks, dan kita ingin mengubahnya menjadi string, mengirimkannya melalui jaringan, atau hanya mengeluarkannya untuk keperluan logging.
Tentu saja, string seperti itu harus mencakup semua properti penting.
Kita dapat menerapkan konversi seperti ini:
biarkan pengguna = { nama: "Yohanes", usia: 30, keString() { return `{nama: "${nama ini}", usia: ${usia ini}}`; } }; peringatan(pengguna); // {nama: "John", umur: 30}
…Tetapi dalam proses pengembangan, properti baru ditambahkan, properti lama diganti namanya dan dihapus. Memperbarui toString
seperti itu setiap saat bisa menyusahkan. Kita bisa mencoba mengulang properti di dalamnya, tapi bagaimana jika objeknya kompleks dan memiliki objek bersarang di properti? Kami juga perlu menerapkan konversinya.
Untungnya, tidak perlu menulis kode untuk menangani semua ini. Tugas sudah terpecahkan.
JSON (JavaScript Object Notation) adalah format umum untuk mewakili nilai dan objek. Hal ini dijelaskan seperti dalam standar RFC 4627. Awalnya dibuat untuk JavaScript, tetapi banyak bahasa lain yang memiliki perpustakaan untuk menanganinya juga. Jadi mudah menggunakan JSON untuk pertukaran data ketika klien menggunakan JavaScript dan server ditulis di Ruby/PHP/Java/Apapun.
JavaScript menyediakan metode:
JSON.stringify
untuk mengubah objek menjadi JSON.
JSON.parse
untuk mengubah JSON kembali menjadi objek.
Misalnya, di sini kita JSON.stringify
seorang siswa:
biarkan siswa = { nama: 'John', usia: 30, isAdmin: salah, kursus: ['html', 'css', 'js'], pasangan: batal }; biarkan json = JSON.stringify(siswa); peringatan(tipe json); // kita punya string! peringatan(json); /* Objek berkode JSON: { "nama": "Yohanes", "usia": 30, "isAdmin": salah, "kursus": ["html", "css", "js"], "pasangan": batal } */
Metode JSON.stringify(student)
mengambil objek dan mengubahnya menjadi string.
String json
yang dihasilkan disebut objek yang dikodekan JSON atau diserialkan atau dirangkai atau disusun . Kami siap mengirimkannya melalui kabel atau dimasukkan ke dalam penyimpanan data biasa.
Harap perhatikan bahwa objek yang dikodekan JSON memiliki beberapa perbedaan penting dari objek literal:
String menggunakan tanda kutip ganda. Tidak ada tanda kutip atau backtick tunggal di JSON. Jadi 'John'
menjadi "John"
.
Nama properti objek juga diberi tanda kutip ganda. Itu wajib. Jadi age:30
menjadi "age":30
.
JSON.stringify
juga dapat diterapkan pada primitif.
JSON mendukung tipe data berikut:
Objek { ... }
Array [ ... ]
Primitif:
string,
angka,
nilai boolean true/false
,
null
.
Misalnya:
// angka di JSON hanyalah angka peringatan( JSON.stringify(1) ) // 1 // string di JSON tetap berupa string, tetapi diberi tanda kutip ganda peringatan( JSON.stringify('test') ) // "tes" peringatan( JSON.stringify(benar) ); // BENAR peringatan( JSON.stringify([1, 2, 3]) ); // [1,2,3]
JSON adalah spesifikasi yang tidak bergantung pada bahasa saja, sehingga beberapa properti objek khusus JavaScript dilewati oleh JSON.stringify
.
Yaitu:
Properti fungsi (metode).
Kunci dan nilai simbolis.
Properti yang menyimpan undefined
.
biarkan pengguna = { sayHi() {// diabaikan peringatan("Halo"); }, [Simbol("id")]: 123, // diabaikan sesuatu: tidak terdefinisi // diabaikan }; peringatan( JSON.stringify(pengguna) ); // {} (objek kosong)
Biasanya tidak apa-apa. Jika bukan itu yang kami inginkan, kami akan segera melihat cara menyesuaikan prosesnya.
Hal hebatnya adalah objek bersarang didukung dan dikonversi secara otomatis.
Misalnya:
ayo bertemu = { judul: "Konferensi", ruang: { nomor: 23, peserta: ["john", "ann"] } }; peringatan( JSON.stringify(pertemuan) ); /* Seluruh struktur dirangkai: { "judul":"Konferensi", "ruangan":{"number":23,"peserta":["john","ann"]}, } */
Batasan penting: tidak boleh ada referensi melingkar.
Misalnya:
biarkan ruangan = { nomor: 23 }; ayo bertemu = { judul: "Konferensi", peserta: ["john", "ann"] }; pertemuan.tempat = ruangan; // ruang referensi pertemuan ruangan.occupiedBy = pertemuan; // pertemuan referensi ruangan JSON.stringify(pertemuan); // Kesalahan: Mengubah struktur melingkar menjadi JSON
Di sini, konversi gagal, karena referensi melingkar: room.occupiedBy
referensi meetup
, dan meetup.place
referensi room
:
Sintaks lengkap JSON.stringify
adalah:
biarkan json = JSON.stringify(nilai[, pengganti, spasi])
nilai
Nilai untuk dikodekan.
pengganti
Array properti untuk dikodekan atau function(key, value)
.
ruang angkasa
Jumlah ruang yang digunakan untuk pemformatan
Seringkali, JSON.stringify
digunakan dengan argumen pertama saja. Namun jika kita perlu menyempurnakan proses penggantian, seperti memfilter referensi melingkar, kita dapat menggunakan argumen kedua JSON.stringify
.
Jika kita meneruskan array properti ke dalamnya, hanya properti ini yang akan dikodekan.
Misalnya:
biarkan ruangan = { nomor: 23 }; ayo bertemu = { judul: "Konferensi", peserta: [{nama: "John"}, {nama: "Alice"}], tempat: ruangan // ruang referensi pertemuan }; ruangan.occupiedBy = pertemuan; // pertemuan referensi ruangan peringatan( JSON.stringify(pertemuan, ['judul', 'peserta']) ); // {"title":"Konferensi","peserta":[{},{}]}
Di sini kami mungkin terlalu ketat. Daftar properti diterapkan ke seluruh struktur objek. Jadi objek yang ada di participants
kosong, karena name
tidak ada di daftar.
Mari sertakan dalam daftar setiap properti kecuali room.occupiedBy
yang akan menyebabkan referensi melingkar:
biarkan ruangan = { nomor: 23 }; ayo bertemu = { judul: "Konferensi", peserta: [{nama: "John"}, {nama: "Alice"}], tempat: ruangan // ruang referensi pertemuan }; ruangan.occupiedBy = pertemuan; // pertemuan referensi ruangan alert( JSON.stringify(pertemuan, ['judul', 'peserta', 'tempat', 'nama', 'nomor']) ); /* { "judul":"Konferensi", "peserta":[{"name":"John"},{"name":"Alice"}], "tempat":{"angka":23} } */
Sekarang semuanya kecuali occupiedBy
sudah diserialkan. Namun daftar propertinya cukup panjang.
Untungnya, kita bisa menggunakan fungsi alih-alih array sebagai replacer
.
Fungsi tersebut akan dipanggil untuk setiap pasangan (key, value)
dan harus mengembalikan nilai “yang diganti”, yang akan digunakan sebagai pengganti nilai asli. Atau undefined
jika nilainya ingin dilewati.
Dalam kasus kami, kami dapat mengembalikan value
"sebagaimana adanya" untuk semuanya kecuali occupiedBy
. Untuk mengabaikan occupiedBy
, kode di bawah ini mengembalikan undefined
:
biarkan ruangan = { nomor: 23 }; ayo bertemu = { judul: "Konferensi", peserta: [{nama: "John"}, {nama: "Alice"}], tempat: ruangan // ruang referensi pertemuan }; ruangan.occupiedBy = pertemuan; // pertemuan referensi ruangan peringatan( JSON.stringify(pertemuan, pengganti fungsi(kunci, nilai) { peringatan(`${kunci}: ${nilai}`); kembali (kunci == 'occupiedBy') ? tidak terdefinisi : nilai; })); /* key:pasangan nilai yang datang sebagai pengganti: : [Objek Objek] judul: Konferensi peserta: [objek objek],[objek objek] 0: [objek objek] nama: John 1: [Objek Objek] nama: Alice tempat: [objek objek] nomor: 23 ditempatiOleh: [Objek Objek] */
Harap dicatat bahwa fungsi replacer
mendapatkan setiap pasangan kunci/nilai termasuk objek bersarang dan item array. Ini diterapkan secara rekursif. Nilai replacer
di dalam this
adalah objek yang berisi properti saat ini.
Panggilan pertama itu istimewa. Itu dibuat menggunakan “objek pembungkus” khusus: {"": meetup}
. Dengan kata lain, pasangan (key, value)
pertama memiliki kunci kosong, dan nilainya adalah objek target secara keseluruhan. Itu sebabnya baris pertama adalah ":[object Object]"
pada contoh di atas.
Idenya adalah untuk memberikan kekuatan sebanyak mungkin kepada replacer
: ia mempunyai kesempatan untuk menganalisis dan mengganti/melewatkan bahkan seluruh objek jika diperlukan.
Argumen ketiga JSON.stringify(value, replacer, space)
adalah jumlah spasi yang digunakan untuk pemformatan cantik.
Sebelumnya, semua objek yang dirangkai tidak memiliki indentasi dan spasi tambahan. Tidak apa-apa jika kita ingin mengirim objek melalui jaringan. Argumen space
digunakan secara eksklusif untuk keluaran yang bagus.
Di sini space = 2
memberitahu JavaScript untuk menampilkan objek bersarang di beberapa baris, dengan lekukan 2 spasi di dalam objek:
biarkan pengguna = { nama: "Yohanes", usia: 25, peran: { isAdmin: salah, adalahEditor: benar } }; peringatan(JSON.stringify(pengguna, null, 2)); /* indentasi dua spasi: { "nama": "Yohanes", "usia": 25, "peran": { "isAdmin": salah, "isEditor": benar } } */ /* untuk JSON.stringify(user, null, 4) hasilnya akan lebih menjorok ke dalam: { "nama": "Yohanes", "usia": 25, "peran": { "isAdmin": salah, "isEditor": benar } } */
Argumen ketiga juga bisa berupa string. Dalam hal ini, string digunakan untuk indentasi, bukan sejumlah spasi.
Parameter space
hanya digunakan untuk tujuan logging dan keluaran yang bagus.
Seperti toString
untuk konversi string, objek dapat menyediakan metode toJSON
untuk konversi ke-JSON. JSON.stringify
secara otomatis memanggilnya jika tersedia.
Misalnya:
biarkan ruangan = { nomor: 23 }; ayo bertemu = { judul: "Konferensi", tanggal: Tanggal baru(Tanggal.UTC(2017, 0, 1)), ruang }; peringatan( JSON.stringify(pertemuan) ); /* { "judul":"Konferensi", "tanggal":"01-01-2017T00:00:00.000Z", // (1) "ruangan": {"angka":23} // (2) } */
Di sini kita dapat melihat bahwa date
(1)
menjadi sebuah string. Itu karena semua tanggal memiliki metode toJSON
bawaan yang mengembalikan string semacam itu.
Sekarang mari tambahkan toJSON
khusus untuk room
objek kita (2)
:
biarkan ruangan = { nomor: 23, keJSON() { kembalikan nomor ini; } }; ayo bertemu = { judul: "Konferensi", ruang }; peringatan( JSON.stringify(ruangan) ); // 23 peringatan( JSON.stringify(pertemuan) ); /* { "judul":"Konferensi", "kamar": 23 } */
Seperti yang bisa kita lihat, toJSON
digunakan untuk panggilan langsung JSON.stringify(room)
dan saat room
disarangkan ke objek lain yang disandikan.
Untuk memecahkan kode string JSON, kita memerlukan metode lain bernama JSON.parse.
Sintaksnya:
biarkan nilai = JSON.parse(str[, menghidupkan kembali]);
str
String JSON untuk diurai.
minuman keras
Fungsi opsional (kunci, nilai) yang akan dipanggil untuk setiap pasangan (key, value)
dan dapat mengubah nilainya.
Misalnya:
// array yang dirangkai misalkan angka = "[0, 1, 2, 3]"; angka = JSON.parse(angka); peringatan(angka[1] ); // 1
Atau untuk objek bersarang:
biarkan userData = '{ "nama": "John", "umur": 35, "isAdmin": false, "teman": [0,1,2,3] }'; biarkan pengguna = JSON.parse(data pengguna); peringatan( pengguna.teman[1] ); // 1
JSON mungkin serumit yang diperlukan, objek dan array dapat menyertakan objek dan array lain. Namun mereka harus mematuhi format JSON yang sama.
Berikut adalah kesalahan umum dalam JSON tulisan tangan (terkadang kita harus menulisnya untuk tujuan debugging):
misalkan json = `{ nama: "John", // kesalahan: nama properti tanpa tanda kutip "nama keluarga": 'Smith', // kesalahan: nilai tanda kutip tunggal (harus ganda) 'isAdmin': false // kesalahan: tanda kutip tunggal pada kunci (harus ganda) "ulang tahun": Tanggal baru (2000, 2, 3), // kesalahan: tidak ada "baru" yang diperbolehkan, hanya nilai kosong "teman": [0,1,2,3] // di sini semuanya baik-baik saja }`;
Selain itu, JSON tidak mendukung komentar. Menambahkan komentar ke JSON membuatnya tidak valid.
Ada format lain bernama JSON5, yang memungkinkan kunci tanpa tanda kutip, komentar, dll. Tapi ini adalah perpustakaan mandiri, bukan dalam spesifikasi bahasanya.
JSON reguler seketat itu bukan karena pengembangnya malas, namun untuk memungkinkan implementasi algoritma parsing yang mudah, andal, dan sangat cepat.
Bayangkan, kita mendapat objek meetup
yang dirangkai dari server.
Ini terlihat seperti ini:
// judul: (judul pertemuan), tanggal: (tanggal pertemuan) let str = '{"title":"Konferensi","tanggal":"30-11-2017T12:00:00.000Z"}';
…Dan sekarang kita perlu melakukan deserialisasi , untuk mengubahnya kembali menjadi objek JavaScript.
Mari kita lakukan dengan memanggil JSON.parse
:
let str = '{"title":"Konferensi","tanggal":"30-11-2017T12:00:00.000Z"}'; biarkan pertemuan = JSON.parse(str); peringatan( bertemu.tanggal.getDate() ); // Kesalahan!
Ups! Sebuah kesalahan!
Nilai meetup.date
adalah string, bukan objek Date
. Bagaimana JSON.parse
dapat mengetahui bahwa ia harus mengubah string tersebut menjadi Date
?
Mari kita lanjutkan ke JSON.parse
fungsi yang dihidupkan kembali sebagai argumen kedua, yang mengembalikan semua nilai "sebagaimana adanya", tetapi date
akan menjadi Date
:
let str = '{"title":"Konferensi","tanggal":"30-11-2017T12:00:00.000Z"}'; biarkan pertemuan = JSON.parse(str, function(key, value) { if (kunci == 'tanggal') mengembalikan Tanggal baru(nilai); nilai kembalian; }); peringatan( bertemu.tanggal.getDate() ); // sekarang berfungsi!
Omong-omong, ini juga berfungsi untuk objek bersarang:
biarkan jadwal = `{ "pertemuan": [ {"title":"Konferensi","tanggal":"30-11-2017T12:00:00.000Z"}, {"title":"Ulang Tahun","tanggal":"18-04-2017T12:00:00.000Z"} ] }`; jadwal = JSON.parse(jadwal, fungsi(kunci, nilai) { if (kunci == 'tanggal') mengembalikan Tanggal baru(nilai); nilai kembalian; }); peringatan( jadwal.pertemuan[1].tanggal.getDate() ); // berhasil!
JSON adalah format data yang memiliki standar dan pustaka independennya sendiri untuk sebagian besar bahasa pemrograman.
JSON mendukung objek biasa, array, string, angka, boolean, dan null
.
JavaScript menyediakan metode JSON.stringify untuk membuat serial menjadi JSON dan JSON.parse untuk membaca dari JSON.
Kedua metode ini mendukung fungsi transformator untuk membaca/menulis dengan cerdas.
Jika suatu objek memiliki toJSON
, maka objek tersebut dipanggil dengan JSON.stringify
.
pentingnya: 5
Ubah user
menjadi JSON lalu baca kembali ke variabel lain.
biarkan pengguna = { nama: "John Smith", usia: 35 };
biarkan pengguna = { nama: "John Smith", usia: 35 }; biarkan pengguna2 = JSON.parse(JSON.stringify(pengguna));
pentingnya: 5
Dalam kasus sederhana referensi melingkar, kita dapat mengecualikan properti yang melanggar dari serialisasi berdasarkan namanya.
Namun terkadang kita tidak bisa hanya menggunakan namanya, karena mungkin digunakan baik dalam referensi melingkar maupun properti normal. Jadi kita bisa memeriksa properti berdasarkan nilainya.
Tulis fungsi replacer
untuk merangkai semuanya, tetapi hapus properti yang mereferensikan meetup
:
biarkan ruangan = { nomor: 23 }; ayo bertemu = { judul: "Konferensi", ditempatiOleh: [{nama: "John"}, {nama: "Alice"}], tempat: kamar }; // referensi melingkar ruangan.occupiedBy = pertemuan; pertemuan.diri = pertemuan; peringatan( JSON.stringify(pertemuan, pengganti fungsi(kunci, nilai) { /* kode Anda */ })); /* hasilnya seharusnya: { "judul":"Konferensi", "occupiedBy":[{"name":"John"},{"name":"Alice"}], "tempat":{"angka":23} } */
biarkan ruangan = { nomor: 23 }; ayo bertemu = { judul: "Konferensi", ditempatiOleh: [{nama: "John"}, {nama: "Alice"}], tempat: kamar }; ruangan.occupiedBy = pertemuan; pertemuan.diri = pertemuan; peringatan( JSON.stringify(pertemuan, pengganti fungsi(kunci, nilai) { kembali (kunci != "" && nilai == pertemuan) ? tidak terdefinisi : nilai; })); /* { "judul":"Konferensi", "occupiedBy":[{"name":"John"},{"name":"Alice"}], "tempat":{"angka":23} } */
Di sini kita juga perlu menguji key==""
untuk mengecualikan panggilan pertama yang value
normal meetup
.