Подтвердить что ты не робот

Как вы используете JSON.stringify карту ES6?

Я хотел бы начать использовать карту ES6 вместо объектов JS, но меня сдерживают, потому что я не могу понять, как JSON.stringify( ) карта. Мои ключи гарантированно будут строками, и мои значения всегда будут списками. Должен ли я действительно писать метод обертки для сериализации?

4b9b3361

Ответ 1

Вы не можете.

Ключами карты могут быть все, включая объекты. Но синтаксис JSON позволяет использовать только строки. Так что это невозможно в общем случае.

Мои ключи гарантированно будут строками, и мои значения всегда будут перечислены

В этом случае вы можете использовать простой объект. Он будет иметь следующие преимущества:

  • Он сможет быть привязан к JSON.
  • Он будет работать в старых браузерах.
  • Это может быть быстрее.

Ответ 2

Вы не можете напрямую преобразовать в строку экземпляр Map поскольку он не имеет никаких свойств, но вы можете преобразовать его в массив кортежей:

jsonText = JSON.stringify(Array.from(map.entries()));

Для обратного используйте

map = new Map(JSON.parse(jsonText));

Ответ 3

Хотя ecmascript еще не предоставил метод, это все же можно сделать с помощью JSON.stingify если вы отобразите Map в примитив JavaScript. Вот пример Map мы будем использовать.

const map = new Map();
map.set('foo', 'bar');
map.set('baz', 'quz');

Переход к объекту JavaScript

Вы можете конвертировать в литерал JavaScript Object с помощью следующей вспомогательной функции.

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"]]'

Ответ 4

И 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);

Ответ 5

Решение ниже работает, даже если у вас есть вложенные Карты

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);
}