Я хотел бы начать использовать карту ES6 вместо объектов JS, но меня сдерживают, потому что я не могу понять, как использовать JSON.stringify () для карты. Мои ключи гарантированно будут строками, и мои значения всегда будут указаны. Мне действительно нужно писать метод-оболочку для сериализации?
112
[...someMap.entries()].join(';')
: для чего-то более сложного вы можете попробовать что-то подобное, используя что-то вроде[...someMap.entries()].reduce((acc, cur) => acc + `${cur[0]}:${/* do something to stringify cur[1] */ }`, '')
obj[key]
может доставить вам что-то неожиданное. Рассмотрим случайif (!obj[key]) obj[key] = newList; else obj[key].mergeWith(newList);
.Ответы:
Оба
JSON.stringify
иJSON.parse
поддерживают второй аргумент.replacer
иreviver
соответственно. С помощью replacer и reviver ниже можно добавить поддержку собственного объекта Map, включая глубоко вложенные значения.function replacer(key, value) { const originalObject = this[key]; if(originalObject instanceof Map) { return { dataType: 'Map', value: Array.from(originalObject.entries()), // or with spread: value: [...originalObject] }; } else { return value; } }
function reviver(key, value) { if(typeof value === 'object' && value !== null) { if (value.dataType === 'Map') { return new Map(value.value); } } return value; }
Использование :
const originalValue = new Map([['a', 1]]); const str = JSON.stringify(originalValue, replacer); const newValue = JSON.parse(str, reviver); console.log(originalValue, newValue);
Глубокая вложение с комбинацией массивов, объектов и карт
const originalValue = [ new Map([['a', { b: { c: new Map([['d', 'text']]) } }]]) ]; const str = JSON.stringify(originalValue, replacer); const newValue = JSON.parse(str, reviver); console.log(originalValue, newValue);
источник
dataType
способами, я не могу придумать более чистого способа. Спасибо.Вы не можете напрямую
Map
преобразовать экземпляр, поскольку у него нет никаких свойств, но вы можете преобразовать его в массив кортежей:jsonText = JSON.stringify(Array.from(map.entries()));
Для обратного используйте
map = new Map(JSON.parse(jsonText));
источник
Map
s, он хорошо сочетается с конструктором и итератором. Кроме того, это единственное разумное представление карт, которые имеют нестроковые ключи, и объект не будет работать там.JSON.stringify(Object.fromEntries(map.entries()))
иnew Map(Object.entries(JSON.parse(jsonText)))
key
это объект, например"{"[object Object]":{"b":2}}"
- ключи объекта являются одной из основных функций КартВы не можете.
Ключи карты могут быть любыми, включая объекты. Но синтаксис JSON позволяет использовать только строки в качестве ключей. Так что в общем случае это невозможно.
В этом случае вы можете использовать простой объект. У него будут следующие преимущества:
источник
hasOwnProperty
. Без этого Firefox выполняет итерацию объектов намного быстрее, чем карты. Однако карты в Chrome по-прежнему работают быстрее. jsperf.com/es6-map-vs-object-properties/95Хотя ecmascript еще не предоставляет метода, это все еще можно сделать,
JSON.stingify
если вы сопоставитеMap
его с примитивом JavaScript. Вот образец, которыйMap
мы будем использовать.const map = new Map(); map.set('foo', 'bar'); map.set('baz', 'quz');
Переход к объекту JavaScript
Вы можете преобразовать в литерал объекта JavaScript с помощью следующей вспомогательной функции.
const mapToObj = m => { return Array.from(m).reduce((obj, [key, value]) => { obj[key] = value; return obj; }, {}); }; JSON.stringify(mapToObj(map)); // '{"foo":"bar","baz":"quz"}'
Переход к массиву объектов JavaScript
Вспомогательная функция для этого была бы еще более компактной
const mapToAoO = m => { return Array.from(m).map( ([k,v]) => {return {[k]:v}} ); }; JSON.stringify(mapToAoO(map)); // '[{"foo":"bar"},{"baz":"quz"}]'
Переход к массиву массивов
Это еще проще, вы можете просто использовать
JSON.stringify( Array.from(map) ); // '[["foo","bar"],["baz","quz"]]'
источник
С помощью spread sytax Map можно сериализовать в одну строку:
JSON.stringify([...new Map()]);
и десериализуйте его с помощью:
let map = new Map(JSON.parse(map));
источник
Стрингируйте
Map
экземпляр (объекты как ключи в порядке) :JSON.stringify([...map])
или
JSON.stringify(Array.from(map))
или
JSON.stringify(Array.from(map.entries()))
Выходной формат:
// [["key1","value1"],["key2","value2"]]
источник
Лучшее решение
// somewhere... class Klass extends Map { toJSON() { var object = { }; for (let [key, value] of this) object[key] = value; return object; } } // somewhere else... import { Klass as Map } from '@core/utilities/ds/map'; // <--wherever "somewhere" is var map = new Map(); map.set('a', 1); map.set('b', { datum: true }); map.set('c', [ 1,2,3 ]); map.set( 'd', new Map([ ['e', true] ]) ); var json = JSON.stringify(map, null, '\t'); console.log('>', json);
Выход
> { "a": 1, "b": { "datum": true }, "c": [ 1, 2, 3 ], "d": { "e": true } }
Надеюсь, это менее неприятно, чем ответы выше.
источник
IJSONAble
интерфейс (конечно, с использованием TypeScript).Решение ниже работает, даже если у вас есть вложенные карты.
function stringifyMap(myMap) { function selfIterator(map) { return Array.from(map).reduce((acc, [key, value]) => { if (value instanceof Map) { acc[key] = selfIterator(value); } else { acc[key] = value; } return acc; }, {}) } const res = selfIterator(myMap) return JSON.stringify(res); }
источник
Map
и (что еще хуже) что каждая вложенная карта (она содержит) также изначально была картой. В противном случае невозможно быть уверенным, что этоarray of pairs
не просто объект, а не Map. Иерархии объектов и массивов не несут этой нагрузки при синтаксическом анализе. Любая правильная сериализацияMap
явно указала бы, что этоMap
.Учитывая, что ваш пример представляет собой простой вариант использования, в котором ключи будут простыми типами, я думаю, что это самый простой способ JSON структурировать карту.
JSON.stringify(Object.fromEntries(map));
Я думаю о базовой структуре данных карты как о массиве пар ключ-значение (как самих массивах). Итак, примерно так:
const myMap = new Map([ ["key1", "value1"], ["key2", "value2"], ["key3", "value3"] ]);
Поскольку эта базовая структура данных - это то, что мы находим в Object.entries, мы можем использовать собственный метод JavaScript для
Object.fromEntries()
Map, как и для Array:Object.fromEntries(myMap); /* { key1: "value1", key2: "value2", key3: "value3" } */
И тогда все, что вам осталось, это использовать JSON.stringify () в результате этого.
источник