JSON merangkai Set


102

Bagaimana satu JSON.stringify () menjadi Set ?

Hal-hal yang tidak berfungsi di Chromium 43:

var s = new Set(['foo', 'bar']);

JSON.stringify(s); // -> "{}"
JSON.stringify(s.values()); // -> "{}"
JSON.stringify(s.keys()); // -> "{}"

Saya berharap untuk mendapatkan sesuatu yang mirip dengan array serial.

JSON.stringify(["foo", "bar"]); // -> "["foo","bar"]"

Jawaban:


108

JSON.stringify tidak langsung bekerja dengan kumpulan karena data yang disimpan dalam kumpulan tidak disimpan sebagai properti.

Tapi Anda bisa mengonversi set ke array. Kemudian Anda akan bisa merangkainya dengan benar.

Salah satu dari berikut ini akan membantu:

JSON.stringify([...s]);
JSON.stringify([...s.keys()]);
JSON.stringify([...s.values()]);
JSON.stringify(Array.from(s));
JSON.stringify(Array.from(s.keys()));
JSON.stringify(Array.from(s.values()));

2
Saya akan melamar Array.from(). Tapi ini terlihat lebih baik secara idiom.
TaoPR

3
Hanya untuk menambahkan beberapa referensi, MDN memiliki beberapa contoh tentang ini dan teknik terkait lainnya
Amit

5
Pemahaman daftar dapat bekerja juga:JSON.stringify([_ for (_ of s)])
Whymarrh

1
Semua cara hebat untuk melakukannya, sayangnya mereka tidak berfungsi di Chromium 43 di luar kotak karena tersebar dan Array.from belum diterapkan. Sepertinya Babel akan menyelamatkan.
MitMaro

2
Proposal saat ini untuk meningkatkan default Set.prototype.toJSON: github.com/DavidBruant/Map-Set.prototype.toJSON
Oncle Tom

34

Gunakan JSON.stringifypengganti ini :

(karena toJSONmerupakan artefak lama, dan pendekatan yang lebih baik adalah menggunakan kustomreplacer , lihat https://github.com/DavidBruant/Map-Set.prototype.toJSON/issues/16 )

function Set_toJSON(key, value) {
  if (typeof value === 'object' && value instanceof Set) {
    return [...value];
  }
  return value;
}

Kemudian:

const fooBar = { foo: new Set([1, 2, 3]), bar: new Set([4, 5, 6]) };
JSON.stringify(fooBar, Set_toJSON)

Hasil:

"{"foo":[1,2,3],"bar":[4,5,6]}"

5
ada versi singkat di ES6JSON.stringify(fooBar, (key, value) => value instanceof Set ? [...value] : value)
OzzyCzech

Reviver yang sesuai dibiarkan sebagai latihan untuk pembaca? ;-)
Robert Siemer

7

Sementara semua pekerjaan di atas saya sarankan agar Anda mengatur subclass dan menambahkan toJSONmetode untuk memastikan bahwa itu merangkai dengan benar. Apalagi jika Anda akan sering merangkai. Saya menggunakan set di toko Redux saya dan perlu memastikan ini tidak pernah menjadi masalah.

Ini adalah implementasi dasar. Penamaan hanya untuk menggambarkan titik pilih gaya Anda sendiri.

class JSONSet extends Set {
    toJSON () {
        return [...this]
    }
}

const set = new JSONSet([1, 2, 3])
console.log(JSON.stringify(set))

4
Saya tidak akan merekomendasikan pendekatan ini karena toJSONdianggap sebagai fitur lama. Proposal untuk ditambahkan toJSONke keduanya setdan mapditolak: github.com/DavidBruant/Map-Set.prototype.toJSON/issues/16
MitMaro

Mengganti constructortidak perlu.
Justin Johnson
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.