Saya memiliki objek besar yang ingin saya konversi ke JSON dan kirim. Namun memiliki struktur melingkar. Saya ingin melemparkan referensi melingkar apa pun yang ada dan mengirim apa pun yang dapat dirangkum. Bagaimana aku melakukan itu?
Terima kasih.
var obj = {
a: "foo",
b: obj
}
Saya ingin menjabarkan obj ke:
{"a":"foo"}
javascript
json
node.js
Harry
sumber
sumber
Jawaban:
Gunakan
JSON.stringify
dengan replacer khusus. Sebagai contoh:Pengganti dalam contoh ini tidak 100% benar (tergantung pada definisi "duplikat" Anda). Dalam kasus berikut, nilai dibuang:
Tapi konsepnya tetap: Gunakan custom replacer, dan pantau nilai objek yang diuraikan.
Sebagai fungsi utilitas yang ditulis dalam es6:
sumber
Node.prototype.toJSON = function() { return 'whatever you think that is right'; };
(jika Anda ingin sesuatu yang lebih umum / spesifik, coba saja apa saja di pohon prototipe: HTMLDivElement mengimplementasikan HTMLElement mengimplementasikan implementements Elemen mengimplementasikan Node mengimplementasikan EventTarget; catatan: ini mungkin tergantung pada browser, pohon sebelumnya berlaku untuk Chrome)var a={id:1}; JSON.stringify([a,a]);
cache
akan menjadi developer.mozilla.org/en-US/docs/Web/JavaScript/… yangDi Node.js, Anda dapat menggunakan util.inspect (objek) . Secara otomatis menggantikan tautan sirkuler dengan "[Circular]".
Meskipun sudah terpasang (tidak diperlukan instalasi) , Anda harus mengimpornya
Untuk menggunakannya, cukup panggilPerlu diketahui juga bahwa Anda dapat melewatkan objek opsi untuk diperiksa (lihat tautan di atas)
Tolong, baca dan berikan pujian kepada komentator di bawah ...
sumber
var util = require('util');
obj_str = util.inspect(thing)
, BUKAN <s>garbage_str = JSON.stringify(util.inspect(thing))
</s>Saya heran mengapa belum ada yang memposting solusi yang tepat dari halaman MDN ...
Nilai yang terlihat harus disimpan dalam satu set , bukan dalam array (replacer dipanggil pada setiap elemen ) dan tidak perlu untuk mencoba
JSON.stringify
setiap elemen dalam rantai yang mengarah ke referensi melingkar.Seperti dalam jawaban yang diterima, solusi ini menghapus semua nilai berulang , bukan hanya yang melingkar. Tetapi setidaknya tidak memiliki kompleksitas eksponensial.
sumber
replacer = () => { const seen = new WeakSet(); return (key, value) => { if (typeof value === "object" && value !== null) { if (seen.has(value)) { return; } seen.add(value); } return value; }; } () => { const seen = new WeakSet(); return (key, value) => { if (typeof value === "object" && value !== null) { if (seen.has(value)) { return; } seen.add(value); … JSON.stringify({a:1, b: '2'}, replacer)
kembaliundefined
dalam chromekerjakan saja
kemudian di file js Anda
https://github.com/WebReflection/circular-json
CATATAN: Saya tidak ada hubungannya dengan paket ini. Tapi saya menggunakannya untuk ini.
Perbarui 2020
Harap dicatat CircularJSON hanya dalam pemeliharaan dan flatted adalah penggantinya.
sumber
JSON
pada prinsipnya.Flatted.stringify({blah: 1})
hasil[{"blah":1}]
) Saya melihat seseorang mencoba mengangkat masalah tentang ini, dan penulis mencaci mereka dan mengunci masalah menjadi komentar.Saya sangat menyukai solusi Trindaz - lebih verbose, tetapi memiliki beberapa bug. Saya memperbaikinya untuk siapa pun yang menyukainya.
Plus, saya menambahkan batas panjang pada objek cache saya.
Jika objek yang saya cetak sangat besar - maksud saya sangat besar - saya ingin membatasi algoritma saya.
sumber
@Jawab RobW benar, tetapi ini lebih berkinerja! Karena menggunakan hashmap / set:
sumber
{"a":{"b":{"a":"d"}}}
dan bahkan menghapus node yang memiliki objek kosong {}Perhatikan bahwa ada juga
JSON.decycle
metode yang diterapkan oleh Douglas Crockford. Lihat cycle.js- nya . Ini memungkinkan Anda untuk merangkai hampir semua struktur standar:Anda juga dapat membuat ulang objek asli dengan
retrocycle
metode. Jadi, Anda tidak harus menghapus siklus dari objek untuk mengencangkannya.Namun ini tidak akan berfungsi untuk DOM Nodes (yang merupakan penyebab khas siklus dalam kasus penggunaan kehidupan nyata). Misalnya ini akan melempar:
Saya telah membuat garpu untuk menyelesaikan masalah itu (lihat garpu cycle.js saya ). Ini seharusnya bekerja dengan baik:
Perhatikan bahwa dalam garpu saya
JSON.decycle(variable)
berfungsi seperti pada aslinya dan akan melemparkan pengecualian ketikavariable
mengandung DOM node / elemen.Ketika Anda menggunakan,
JSON.decycle(variable, true)
Anda menerima kenyataan bahwa hasilnya tidak akan dapat dibalikkan (retrocycle tidak akan membuat kembali node DOM). Elemen DOM harus dapat diidentifikasi sampai batas tertentu. Misalnya jika suatudiv
elemen memiliki id maka itu akan diganti dengan string"div#id-of-the-element"
.sumber
JSON.decycle(a, true)
apa yang terjadi ketika Anda meneruskan true sebagai parameter untuk mendaur ulang fungsi.stringifyNodes
opsi benar dalam garpu. Ini akan membuang misalnyadiv
dengan id = "beberapa-id" string:div#some-id
. Anda akan menghindari beberapa masalah, tetapi Anda tidak akan dapat sepenuhnya retro-cycle.Saya akan merekomendasikan memeriksa json-stringify-safe dari @ isaacs-- ini digunakan dalam NPM.
Untuk memasang:
Menggunakan:
Ini menghasilkan:
sumber
Untuk googler di masa depan mencari solusi untuk masalah ini ketika Anda tidak tahu kunci dari semua referensi melingkar, Anda bisa menggunakan pembungkus di sekitar fungsi JSON.stringify untuk mengesampingkan referensi melingkar. Lihat contoh skrip di https://gist.github.com/4653128 .
Solusinya pada dasarnya bermuara pada menjaga referensi ke objek yang sebelumnya dicetak dalam array, dan memeriksa bahwa dalam fungsi replacer sebelum mengembalikan nilai. Ini lebih konstriksi daripada hanya mengesampingkan referensi melingkar, karena itu juga mengesampingkan pernah mencetak objek dua kali, salah satu sisi yang mempengaruhi adalah untuk menghindari referensi melingkar.
Pembungkus contoh:
sumber
if(printedObjIndex)
sementara Anda harus menulisif(printedObjIndex==false)
karenaindex
bisa juga0
yang diterjemahkanfalse
kecuali Anda secara eksplisit menyatakan sebaliknya.===
?0 == false
adalahtrue
,0 === false
adalahfalse
. ; ^) Tapi saya lebih suka tidak menginisialisasiprintedObjIndex
ke false, karena Anda dapat memeriksaundefined
sehingga Anda (well, Trindaz's) tidak mencampur metafora aneh.Gunakan metode JSON.stringify dengan replacer. Baca dokumentasi ini untuk informasi lebih lanjut. http://msdn.microsoft.com/en-us/library/cc836459%28v=vs.94%29.aspx
Mencari cara untuk mengisi array pengganti dengan referensi siklik. Anda dapat menggunakan metode typeof untuk menemukan apakah properti bertipe 'objek' (referensi) dan pemeriksaan kesetaraan yang tepat (===) untuk memverifikasi referensi melingkar.
sumber
var obj = {foo:obj}
tidak tidak membuat referensi melingkar. Alih-alih, ia membuat objek yangfoo
atributnya merujuk pada nilai sebelumnyaobj
(undefined
jika tidak ditentukan sebelumnya, dideklarasikan karenavar obj
).Jika
menghasilkan a
Maka Anda mungkin ingin mencetak seperti ini:
sumber
mengevaluasi ke:
dengan fungsi:
sumber
Saya tahu ini adalah pertanyaan lama, tetapi saya ingin menyarankan paket NPM yang saya buat disebut smart-circular , yang bekerja secara berbeda dari cara lain yang diusulkan. Ini sangat berguna jika Anda menggunakan benda besar dan dalam .
Beberapa fitur adalah:
Mengganti referensi melingkar atau hanya mengulangi struktur di dalam objek dengan jalan menuju kemunculan pertamanya (bukan hanya string [melingkar] );
Dengan mencari bundaran dalam pencarian pertama yang luas, paket memastikan jalur ini sekecil mungkin, yang penting ketika berhadapan dengan objek yang sangat besar dan dalam, di mana jalur bisa menjadi panjang dan sulit untuk diikuti (penggantian kustom di JSON.stringify melakukan DFS);
Mengizinkan penggantian yang dipersonalisasi, berguna untuk menyederhanakan atau mengabaikan bagian objek yang kurang penting;
Akhirnya, jalur ditulis persis seperti yang diperlukan untuk mengakses bidang yang dirujuk, yang dapat membantu Anda melakukan debug.
sumber
Argumen kedua untuk JSON.stringify () juga memungkinkan Anda untuk menentukan array nama kunci yang harus dipertahankan dari setiap objek yang ditemui dalam data Anda. Ini mungkin tidak berfungsi untuk semua kasus penggunaan, tetapi merupakan solusi yang jauh lebih sederhana.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
Catatan: Anehnya, definisi objek dari OP tidak menimbulkan kesalahan referensi melingkar di Chrome atau Firefox terbaru. Definisi dalam jawaban ini telah dimodifikasi sehingga tidak menimbulkan kesalahan.
sumber
Untuk memperbarui jawaban untuk mengganti cara kerja JSON (mungkin tidak disarankan, tetapi sangat sederhana), jangan gunakan
circular-json
(sudah usang). Alih-alih, gunakan penerusnya, yang diratakan:https://www.npmjs.com/package/flatted
Dipinjam dari jawaban lama di atas dari @ user1541685, tetapi diganti dengan yang baru:
npm i --save flatted
kemudian di file js Anda
sumber
Saya menemukan perpustakaan melingkar-json di github dan itu bekerja dengan baik untuk masalah saya.
Beberapa fitur bagus yang menurut saya berguna:
sumber
Saya mengatasi masalah ini seperti ini:
sumber
_class: ClassName { data: "here" }
, jadi saya menambahkan aturan berikut.replace(/(\w+) {/g, '{ __ClassName__: "$1", ')
. Dalam kasus saya, saya mencoba untuk melihat seperti apa objek permintaan http.Saya tahu pertanyaan ini sudah lama dan memiliki banyak jawaban, tetapi saya memposting jawaban ini karena rasanya yang baru (es5 +)
Tampilkan cuplikan kode
sumber
Meskipun ini telah dijawab dengan cukup, Anda juga dapat secara eksplisit menghapus properti yang dipertanyakan sebelum pengerasan menggunakan
delete
operator.hapus operator
ini akan menghapus kebutuhan untuk membangun atau mempertahankan logika kompleks untuk menghapus referensi melingkar.
sumber
sumber
solusi lain untuk menyelesaikan masalah ini dengan objek semacam ini adalah menggunakan perpustakaan ini
https://github.com/ericmuyser/stringy
itu sederhana dan Anda dapat dalam beberapa langkah sederhana menyelesaikan ini.
sumber
Berdasarkan jawaban lain saya berakhir dengan kode berikut. Ini bekerja cukup baik dengan referensi melingkar, objek dengan konstruktor khusus.
Dari objek yang diberikan untuk diserialisasi,
Github Link - DecycledJSON
Contoh Penggunaan 1:
Contoh Penggunaan 2:
sumber
Coba ini:
sumber
seen.push(value)
= -D? Sukafor (var key in value) {value[key] = circular_replacer(value[key]);}
Dalam solusi saya, jika Anda mengalami siklus, itu tidak hanya mengatakan "siklus" (atau tidak sama sekali), ia mengatakan sesuatu seperti foo: lihat objek # 42 di atas, dan untuk melihat di mana foo menunjuk Anda dapat menggulir ke atas dan mencari untuk objek # 42 (setiap objek, ketika dimulai, mengatakan objek # xxx dengan beberapa bilangan bulat xxx)
Potongan:
sumber