JSON stringify Set


102

Як би один JSON.stringify () в комплект ?

Речі, які не працювали в Chromium 43:

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

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

Я очікував би отримати щось подібне до серіалізованого масиву.

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

Відповіді:


108

JSON.stringify не працює безпосередньо з наборами, оскільки дані, що зберігаються в наборі, не зберігаються як властивості.

Але ви можете перетворити набір у масив. Тоді ви зможете правильно його розтягнути.

Будь-що з наведеного нижче зробить трюк:

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
Я збирався запропонувати Array.from(). Але це виглядає ідіомічно краще.
TaoPR

3
Просто щоб додати посилання MDN має кілька прикладів цього та інших суміжних прийомів
Аміт

5
JSON.stringify([_ for (_ of s)])
Розуміння

1
Всі чудові способи зробити це, на жаль, вони не працюють у Chromium 43 нестандартно, оскільки розповсюдження та Array.from ще не реалізовані. Схоже, Бабель на допомогу.
MitMaro

2
Поточна пропозиція щодо покращення за замовчуванням Set.prototype.toJSON: github.com/DavidBruant/Map-Set.prototype.toJSON
Oncle Tom,

34

Використовуйте цей JSON.stringifyзамінник:

(оскільки toJSONце застарілий артефакт, а кращий підхід - використовувати спеціальнийreplacer , див. 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;
}

Тоді:

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

Результат:

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

5
в ES6 є скорочена версіяJSON.stringify(fooBar, (key, value) => value instanceof Set ? [...value] : value)
OzzyCzech

Відповідний відроджувач залишено як вправу для читача? ;-)
Роберт Сімер,

7

Хоча все вищезазначене працює, я пропоную вам підклас встановити та додати toJSONметод, щоб переконатись, що він правильно розшифрований. Особливо, якщо ви збираєтеся часто стригувати. Я використовую набори в своїх магазинах Redux і мені потрібно було переконатися, що це ніколи не є проблемою.

Це основна реалізація. Присвоєння імен лише для того, щоб проілюструвати суть вибору власного стилю.

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

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

4
Я б не рекомендував такий підхід, оскільки toJSONце вважається застарілою функцією. Пропозиція додати toJSONдо обох setі mapбув відхилений: github.com/DavidBruant/Map-Set.prototype.toJSON/issues/16
MitMaro

Заміна constructorне потрібна.
Джастін Джонсон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.