आप JSON.string को ES6 मैप कैसे बनाते हैं?


105

मैं JS ऑब्जेक्ट्स के बजाय ES6 मैप का उपयोग शुरू करना चाहता हूं, लेकिन मुझे वापस रखा जा रहा है क्योंकि मैं JSON.stringify () मैप के बारे में पता नहीं लगा सकता हूं। मेरी कुंजी को तार होने की गारंटी है और मेरे मूल्य हमेशा सूचीबद्ध होंगे। क्या मुझे धारावाहिक बनाने के लिए एक रैपर विधि लिखनी होगी?


1
विषय पर दिलचस्प लेख 2ality.com/2015/08/es6-map-json.html
डेविड चेस

मैं यह काम करने में सक्षम था। परिणाम Plunkr पर embed.plnkr.co/oNlQQBDyJUiIQlgWUPVP पर हैं । समाधान एक JSON.stringify (obj, replacerFunction) का उपयोग करता है जो यह देखने के लिए जांचता है कि क्या कोई मैप ऑब्जेक्ट पास किया जा रहा है और मैप ऑब्जेक्ट को जावास्क्रिप्ट ऑब्जेक्ट में परिवर्तित करता है (जो JSON.stringify) तो एक स्ट्रिंग में परिवर्तित हो जाएगा।
पेट्स

1
यदि आपकी चाबियाँ तार (या संख्या) और आपके मूल्यों के सरणियों की गारंटी हैं , तो आप कुछ ऐसा कर सकते हैं [...someMap.entries()].join(';'); कुछ और अधिक जटिल के लिए आप कुछ का उपयोग करके कुछ इसी तरह की कोशिश कर सकते हैं[...someMap.entries()].reduce((acc, cur) => acc + `${cur[0]}:${/* do something to stringify cur[1] */ }`, '')
user56reinstatemonica8

@Oriol यदि डिफ़ॉल्ट नाम के समान गुण होना संभव है तो क्या होगा? obj[key]आपको कुछ अप्रत्याशित मिल सकता है। मामले पर विचार करें if (!obj[key]) obj[key] = newList; else obj[key].mergeWith(newList);
फ्रैंकलिन यू

जवाबों:


65

आप नहीं कर सकते।

मानचित्रों की कुंजियाँ कुछ भी हो सकती हैं, जिसमें वस्तुएँ भी शामिल हैं। लेकिन JSON सिंटैक्स केवल स्ट्रिंग्स को कुंजी के रूप में अनुमति देता है। इसलिए एक सामान्य मामले में यह असंभव है।

मेरी कुंजियाँ तार होने की गारंटी हैं और मेरे मूल्य हमेशा सूचियाँ होंगी

इस मामले में, आप एक सादे वस्तु का उपयोग कर सकते हैं। इसके ये फायदे होंगे:

  • यह JSON के लिए कड़ा हो जाएगा।
  • यह पुराने ब्राउज़रों पर काम करेगा।
  • यह तेज हो सकता है।

31
जिज्ञासु के लिए, नवीनतम क्रोम में, कोई भी मानचित्र '{}' में
अनुक्रमित होता है

मैंने यहाँ बताया है कि वास्तव में मेरा क्या मतलब है जब मैंने कहा कि "आप नहीं कर सकते"।
ओरोल

7
"यह तेज़ हो सकता है" - क्या आपके पास उस पर कोई स्रोत है? मैं कल्पना कर रहा हूं कि एक साधारण हैश-मैप पूर्ण विकसित वस्तु की तुलना में तेज होना चाहिए, लेकिन मेरे पास कोई सबूत नहीं है। :)
लिलेमन

1
@Xplouder वह परीक्षण महंगा उपयोग करता है hasOwnProperty। इसके बिना, फ़ायरफ़ॉक्स नक्शे की तुलना में बहुत तेज़ी से वस्तुओं को पुन: प्रसारित करता है। Chrome पर मानचित्र अभी भी तेज़ हैं, हालाँकि। jsperf.com/es6-map-vs-object-properties/95
ओरोल

1
यह सच है, लगता है कि फ़ायरफ़ॉक्स 45v क्रोम + 49 वी की तुलना में वस्तुओं को तेजी से प्रसारित करता है। हालाँकि क्रोम में मैप्स अभी भी बनाम वस्तुओं को जीतते हैं।
Xplouder 19

71

आप सीधे इसका Mapउदाहरण नहीं बता सकते क्योंकि इसमें कोई गुण नहीं है, लेकिन आप इसे टुपल्स की एक सरणी में बदल सकते हैं:

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

रिवर्स के लिए, का उपयोग करें

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

6
यह JSON ऑब्जेक्ट में परिवर्तित नहीं होता है, बल्कि Array के Array के बजाय होता है। एक ही बात नहीं है। अधिक संपूर्ण उत्तर के लिए इवान कैरोल का उत्तर नीचे देखें।
शनि तिरु

3
@SatThiru tuples की एक सरणी s का प्रथागत प्रतिनिधित्व है Map, यह कंस्ट्रक्टर और पुनरावृत्त के साथ अच्छी तरह से चला जाता है। इसके अलावा यह गैर-स्ट्रिंग कुंजी वाले नक्शे का एकमात्र समझदार प्रतिनिधित्व है, और ऑब्जेक्ट वहां काम नहीं करेगा।
बरगी

बरगी, कृपया ध्यान दें कि ओपी ने कहा "मेरी चाबी तार होने की गारंटी है"।
शनि तिरु

4
@SatThiru उस मामले में, का उपयोग करें JSON.stringify(Object.fromEntries(map.entries()))औरnew Map(Object.entries(JSON.parse(jsonText)))
Bergi

@Bergi Stringify काम नहीं करता है अगर keyएक वस्तु है जैसे "{"[object Object]":{"b":2}}"- ऑब्जेक्ट कुंजी मैप्स की मुख्य विशेषताओं में से एक है
Drenai

59

दोनों JSON.stringifyऔर JSON.parseएक दूसरे तर्क का समर्थन। replacerऔर reviverक्रमशः। नीचे दिए गए replacer और reviver के साथ मूल मैप ऑब्जेक्ट के लिए समर्थन जोड़ना संभव है, जिसमें गहरे नेस्टेड मान शामिल हैं

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

8
यह अब तक की सबसे अच्छी प्रतिक्रिया है
मैनुअल वेला सिल्वेस्ट्रे

1
निश्चित रूप से यहाँ सबसे अच्छा जवाब।
जावारनर

15

हालांकि अभी तक परासरण द्वारा कोई विधि प्रदान नहीं की गई है, यह तब भी किया जा सकता है JSON.stingifyयदि आप Mapजावास्क्रिप्ट आदिम में मैप करते हैं । यहाँ नमूना Mapहम उपयोग करेंगे।

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

जावास्क्रिप्ट ऑब्जेक्ट पर जा रहे हैं

आप निम्न सहायक फ़ंक्शन के साथ जावास्क्रिप्ट ऑब्जेक्ट शाब्दिक में बदल सकते हैं।

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

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

ऑब्जेक्ट के जावास्क्रिप्ट ऐरे में जाना

इस एक के लिए सहायक समारोह और भी अधिक कॉम्पैक्ट होगा

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

13

स्प्रेड सिक्सैक्स का उपयोग करके मानचित्र को एक पंक्ति में क्रमबद्ध किया जा सकता है:

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

और इसके साथ इसका वर्णन करें:

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

यह एक-आयामी मानचित्र के लिए काम करेगा, लेकिन n-आयामी मानचित्र के लिए नहीं।
mattsven

6

एक Mapउदाहरण को स्ट्रिंग करें (ऑब्जेक्ट ठीक हैं के रूप में) :

JSON.stringify([...map])

या

JSON.stringify(Array.from(map))

या

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

आउटपुट स्वरूप:

// [["key1","value1"],["key2","value2"]]

4

एक बेहतर समाधान

    // 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
        }
    }

आशा है कि उपरोक्त उत्तरों की तुलना में कम समालोचक है।


मुझे यकीन नहीं है कि बहुत से लोग इसे मैप करने के लिए कोर मैप क्लास का विस्तार करने से संतुष्ट हो जाएंगे ...
vasia

1
वे होना नहीं है, लेकिन यह इसे करने का एक अधिक ठोस तरीका है। विशेष रूप से, यह एलओएलडी और ओसीपी के ठोस सिद्धांतों के साथ संरेखित करता है। यही है, देशी मैप को विस्तारित किया जा रहा है, संशोधित नहीं किया गया है और एक अभी भी देशी मैप के साथ लिस्कोव सबस्टीट्यूशन (एलएसपी) का उपयोग कर सकता है। दी, यह बहुत सारे नौसिखियों या कट्टर कार्यात्मक प्रोग्रामिंग से अधिक ओओपी है जो लोग पसंद करेंगे, लेकिन कम से कम यह मूलभूत सॉफ़्टवेयर डिज़ाइन सिद्धांतों की कोशिश की गई और सही आधार रेखा के बगल में है। यदि आप SOLID के इंटरफ़ेस सेग्रीगेशन सिद्धांत (ISP) को लागू करना चाहते हैं, तो आपके पास एक छोटा IJSONAbleइंटरफ़ेस (टाइपस्क्रिप्ट का उपयोग करके, निश्चित रूप से) हो सकता है।
कोडी

3

यदि आपके पास मैप्स नेस्टेड हैं, तो भी नीचे समाधान काम करता है

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

आपके जवाब का परीक्षण किए बिना, मैं पहले से ही सराहना करता हूं कि यह नेस्टेड मैप्स की समस्या पर ध्यान कैसे लाता है। यहां तक ​​कि अगर आप इसे सफलतापूर्वक JSON में परिवर्तित करते हैं, तो भविष्य में किए गए किसी भी पार्सिंग में स्पष्ट जागरूकता है कि JSON मूल रूप से एक Map(और भी बदतर) था कि प्रत्येक उप-नक्शा (इसमें शामिल है) भी मूल रूप से एक नक्शा था। अन्यथा, यह सुनिश्चित करने का कोई तरीका array of pairsनहीं है कि मैप के बजाय केवल ऐसा होना बिल्कुल नहीं है। वस्तुओं और सरणियों के पदानुक्रम इस बोझ को पार नहीं करते हैं। के किसी भी उचित क्रमांकन से Mapस्पष्ट रूप से संकेत मिलता है कि यह एक है Map
लोनी बेस्ट

इसके बारे में यहाँ और अधिक ।
लोनी बेस्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.