JSON xâu chuỗi một Tập hợp


102

Làm thế nào để một JSON.stringify () một Tập hợp ?

Những điều không hoạt động trong Chromium 43:

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

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

Tôi mong đợi nhận được một cái gì đó tương tự như của một mảng được tuần tự hóa.

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

Câu trả lời:


108

JSON.stringify không trực tiếp hoạt động với tập hợp vì dữ liệu được lưu trữ trong tập hợp không được lưu trữ dưới dạng thuộc tính.

Nhưng bạn có thể chuyển tập hợp thành một mảng. Sau đó, bạn sẽ có thể xâu chuỗi nó đúng cách.

Bất kỳ thao tác nào sau đây sẽ thực hiện thủ thuật:

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
Tôi sẽ cầu hôn Array.from(). Nhưng điều này có vẻ tốt hơn về mặt thành ngữ.
TaoPR

3
Chỉ để thêm một số tài liệu tham khảo MDN có một số ví dụ về điều này và các kỹ thuật có liên quan khác
Amit

5
JSON.stringify([_ for (_ of s)])
Khả

1
Tất cả những cách tuyệt vời để làm điều đó, thật đáng buồn là chúng không hoạt động trong Chromium 43 ngay lập tức vì spread và Array.from vẫn chưa được triển khai. Có vẻ như Babel đến giải cứu.
MitMaro

2
Đề xuất hiện tại để cải thiện mặc định của Set.prototype.toJSON: github.com/DavidBruant/Map-Set.prototype.toJSON
Oncle Tom

34

Sử dụng JSON.stringifychất thay thế này :

(vì toJSONlà phần mềm kế thừa và cách tiếp cận tốt hơn là sử dụng tùy chỉnhreplacer , hãy xem 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;
}

Sau đó:

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

Kết quả:

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

5
có phiên bản rút gọn trong ES6JSON.stringify(fooBar, (key, value) => value instanceof Set ? [...value] : value)
OzzyCzech

Trình hồi sinh tương ứng được để lại như một bài tập cho người đọc? ;-)
Robert Siemer

7

Trong khi tất cả các công việc trên, tôi khuyên bạn nên đặt lớp con và thêm một toJSONphương thức để đảm bảo rằng nó được xâu chuỗi chính xác. Đặc biệt nếu bạn thường xuyên lập chuỗi. Tôi sử dụng các bộ trong các cửa hàng Redux của mình và cần đảm bảo rằng điều này không bao giờ là vấn đề.

Đây là một cách thực hiện cơ bản. Đặt tên chỉ để minh họa cho điểm chọn phong cách của riêng bạn.

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

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

4
Tôi sẽ không đề xuất phương pháp này vì toJSONđược coi là một tính năng kế thừa. Đề xuất thêm toJSONvào cả hai setmapđã bị từ chối: github.com/DavidBruant/Map-Set.prototype.toJSON/issues/16
MitMaro

Ghi đè constructorlà không cần thiết.
Justin Johnson
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.