Jak się masz JSON?stringify na mapie ES6?

Chciałbym zacząć używać ES6 Map zamiast obiektów JS, ale jestem wstrzymywany, ponieważ nie mogę rozgryźć, jak JSON.stringify () Mapa Moje klucze są gwarantowane jako ciągi, a moje wartości będą zawsze wyświetlane. Czy naprawdę muszę pisać metodę wrappera, aby serializować?

Author: Yashwardhan Pauranik, 2015-03-16

9 answers

Zarówno JSON.stringify jak i JSON.parse wspierają drugi argument. replacer i reviver odpowiednio. Z replacer i reviver poniżej można dodać obsługę natywnego obiektu Map, w tym głęboko zagnieżdżonych wartości

function replacer(key, value) {
  if(value instanceof Map) {
    return {
      dataType: 'Map',
      value: Array.from(value.entries()), // or with spread: value: [...value]
    };
  } else {
    return value;
  }
}
function reviver(key, value) {
  if(typeof value === 'object' && value !== null) {
    if (value.dataType === 'Map') {
      return new Map(value.value);
    }
  }
  return value;
}

Użycie :

const originalValue = new Map([['a', 1]]);
const str = JSON.stringify(originalValue, replacer);
const newValue = JSON.parse(str, reviver);
console.log(originalValue, newValue);

Głębokie zagnieżdżanie z kombinacją tablic, obiektów i map

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);
 102
Author: Pawel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-27 09:33:42

Nie można bezpośrednio stringować instancji Map, ponieważ nie ma ona żadnych właściwości, ale można ją przekonwertować na tablicę krotek:

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

Na odwrót, użyj

map = new Map(JSON.parse(jsonText));
 79
Author: Bergi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-24 19:10:50

Nie możesz.

Kluczami mapy może być wszystko, łącznie z obiektami. Ale składnia JSON zezwala tylko na ciągi jako klucze. Więc to niemożliwe w ogólnym przypadku.

Moje klucze są gwarantowane jako ciągi znaków, a moje wartości zawsze będą listami

W tym przypadku można użyć zwykłego obiektu. Będzie miał te zalety:

  • będzie można przeciągnąć do JSON.
  • będzie działać na starszych przeglądarkach.
  • Może być szybciej.
 67
Author: Oriol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-16 19:42:15

Chociaż nie ma jeszcze żadnej metody dostarczonej przez ecmascript, można to zrobić za pomocą JSON.stingify, Jeśli odwzorujesz Map na prymitywny JavaScript. Oto próbka Map, której użyjemy.

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

Przejście do obiektu JavaScript

Można przekonwertować na literalny obiekt JavaScript za pomocą następującej funkcji pomocniczej.

const mapToObj = m => {
  return Array.from(m).reduce((obj, [key, value]) => {
    obj[key] = value;
    return obj;
  }, {});
};

JSON.stringify(mapToObj(map)); // '{"foo":"bar","baz":"quz"}'

Przejście do tablicy obiektów JavaScript

Funkcja pomocnicza dla tego byłaby jeszcze bardziej zwarta

const mapToAoO = m => {
  return Array.from(m).map( ([k,v]) => {return {[k]:v}} );
};

JSON.stringify(mapToAoO(map)); // '[{"foo":"bar"},{"baz":"quz"}]'

Going to Array of Tablice

Jest to jeszcze łatwiejsze, możesz po prostu użyć

JSON.stringify( Array.from(map) ); // '[["foo","bar"],["baz","quz"]]'
 18
Author: Evan Carroll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-11 05:42:10

Używając spread Sytax mapa może być serializowana w jednej linii:

JSON.stringify([...new Map()]);

I deserializuj przez:

let map = new Map(JSON.parse(map));
 18
Author: metodribic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-26 13:02:52

Stringify a Map instancja (obiekty jako klucze są w porządku):

JSON.stringify([...map])

Lub

JSON.stringify(Array.from(map))

Lub

JSON.stringify(Array.from(map.entries()))

Format wyjściowy:

// [["key1","value1"],["key2","value2"]]
 8
Author: am0wa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-25 12:54:00

Lepsze Rozwiązanie

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

Wyjście

    > {
        "a": 1,
        "b": {
            "datum": true
        },
        "c": [
            1,
            2,
            3
        ],
        "d": {
            "e": true
        }
    }

Mam nadzieję, że jest to mniej krzywe niż odpowiedzi powyżej.

 6
Author: Cody,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-15 17:57:56

Biorąc pod uwagę, że twój przykład jest prostym przypadkiem użycia, w którym klucze będą prostymi typami, myślę, że jest to najprostszy sposób na JSON stringify Mapy.

JSON.stringify(Object.fromEntries(map));

Sposób, w jaki myślę o podstawowej strukturze danych mapy jest tablicą par klucz-wartość (jako same tablice). Coś w tym stylu:

const myMap = new Map([
     ["key1", "value1"],
     ["key2", "value2"],
     ["key3", "value3"]
]);

Ponieważ ta podstawowa struktura danych jest tym, co znajdujemy w obiekcie.wpisy, możemy wykorzystać natywną metodę JavaScript Object.fromEntries() na mapie tak jak na Tablica:

Object.fromEntries(myMap);

/*
{
     key1: "value1",
     key2: "value2",
     key3: "value3"
}
*/

I zostaje Ci tylko używanie JSON.stringify () na wynik tego.

 5
Author: Alok Somani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-18 05:09:12

Poniżej rozwiązanie działa nawet jeśli masz zagnieżdżone Mapy

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);
}
 4
Author: Imamudin Naseem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-18 10:20:17