सॉर्ट ऑब्जेक्ट गुण और JSON.stringify


94

मेरे आवेदन में वस्तुओं का एक बड़ा सरणी है, जिसे मैं डिस्क पर स्ट्रिंग करता हूं और सहेजता हूं। दुर्भाग्य से, जब सरणी में वस्तुओं को हेरफेर किया जाता है, और कभी-कभी प्रतिस्थापित किया जाता है, तो वस्तुओं पर गुणों को अलग-अलग क्रम (उनके प्रतिस्थापन क्रम?) में सूचीबद्ध किया जाता है। जब मैं सरणी पर JSON.stringify () करता हूं और इसे सहेजता हूं, तो एक भिन्न गुण अलग-अलग आदेशों में सूचीबद्ध होने वाले गुणों को दिखाता है, जो डेटा को अलग और विलय के साथ आगे विलय करने की कोशिश करते समय कष्टप्रद होता है।

आदर्श रूप से मैं स्ट्रिंग के प्रदर्शन से पहले, या स्ट्रिंग ऑपरेशन के हिस्से के रूप में वस्तुओं के गुणों को वर्णानुक्रम में क्रमबद्ध करना चाहूंगा। कई स्थानों पर सरणी वस्तुओं में हेरफेर करने के लिए कोड है, और एक स्पष्ट क्रम में हमेशा गुण बनाने के लिए इन्हें बदलना मुश्किल होगा।

सुझावों का सबसे अधिक स्वागत होगा!

एक गाढ़ा उदाहरण:

obj = {}; obj.name="X"; obj.os="linux";
JSON.stringify(obj);
obj = {}; obj.os="linux"; obj.name="X";
JSON.stringify(obj);

इन दो स्ट्रिफ़ाइज़ कॉल्स का आउटपुट अलग-अलग है, और मेरे डेटा के एक अलग हिस्से में दिखाई दे रहा है, लेकिन मेरा एप्लिकेशन गुणों के क्रम की परवाह नहीं करता है। वस्तुओं का निर्माण कई तरीकों और स्थानों पर किया जाता है।


कृपया उस वस्तु का उदाहरण दें जिसे आप (या तो जेएसएन आउटपुट या जेएस ऑब्जेक्ट शाब्दिक रूप से) संशोधित करने का प्रयास कर रहे हैं
Bojangles

4
ऑब्जेक्ट में ऑब्जेक्ट की कुंजियाँ एक निश्चित क्रम के लिए गारंटी नहीं हैं। यह डिजाइन द्वारा है।
राहगीर

1
stackoverflow.com/questions/1359761/sorting-a-javascript-object आपकी मदद कर सकता है
सतपाल

1
@rab, आपको यह कहां से पता चला? नोट: यह काम कर सकता है (और शायद ज्यादातर समय होता है), लेकिन मेरा मतलब था कि इसकी गारंटी नहीं है।
डॉगबर्ट

1
यहां ओ.पी. यहां संपत्ति के आदेश पर कोई निर्भरता नहीं थी, बस क्रमबद्ध डेटा में अंतर से बचने के तरीके पर एक सवाल था। यह अंत में सरणियों में गुणों को मारकर और क्रमबद्धता से पहले उन्हें छांट कर हल किया गया था, बहुत कुछ नीचे दिए गए उत्तर की तरह।
अभिनव

जवाबों:


73

सरल, आधुनिक और वर्तमान में ब्राउज़र समर्थित दृष्टिकोण बस यही है:

JSON.stringify(sortMyObj, Object.keys(sortMyObj).sort());

हालाँकि, यह विधि किसी भी नेस्टेड ऑब्जेक्ट को संदर्भित नहीं करती है जो संदर्भित नहीं हैं और सरणियों के भीतर ऑब्जेक्ट पर लागू नहीं होते हैं। आप छँटाई वस्तु के रूप में अच्छी तरह से अगर आप इस उत्पादन की तरह कुछ करना चाहते हैं:

{"a":{"h":4,"z":3},"b":2,"c":1}

आप इसके साथ ऐसा कर सकते हैं:

var flattenObject = function(ob) {
    var toReturn = {};

    for (var i in ob) {
        if (!ob.hasOwnProperty(i)) continue;

        if ((typeof ob[i]) == 'object') {
            var flatObject = flattenObject(ob[i]);
            for (var x in flatObject) {
                if (!flatObject.hasOwnProperty(x)) continue;

                toReturn[i + '.' + x] = flatObject[x];
            }
        } else {
            toReturn[i] = ob[i];
        }
    }
    return toReturn;
};

JSON.stringify(sortMyObj, Object.keys(flattenObject(sortMyObj)).sort());

प्रोग्राम के साथ ऐसा करने के लिए आप अपने आप को ट्वीक कर सकते हैं, आपको ऑब्जेक्ट प्रॉपर्टी के नामों को एक एरे में पुश करने की आवश्यकता है, फिर उस ऐरे के माध्यम से एरे वर्णानुक्रम में टाइप करें और (जो कि सही क्रम में होगा) और ऑब्जेक्ट में से प्रत्येक मान का चयन करें वह आदेश। "hasOwnProperty" की जाँच की जाती है, इसलिए आपके पास निश्चित रूप से केवल ऑब्जेक्ट के अपने गुण हैं। यहाँ एक उदाहरण है:

var obj = {"a":1,"b":2,"c":3};

function iterateObjectAlphabetically(obj, callback) {
    var arr = [],
        i;

    for (i in obj) {
        if (obj.hasOwnProperty(i)) {
            arr.push(i);
        }
    }

    arr.sort();

    for (i = 0; i < arr.length; i++) {
        var key = obj[arr[i]];
        //console.log( obj[arr[i]] ); //here is the sorted value
        //do what you want with the object property
        if (callback) {
            // callback returns arguments for value, key and original object
            callback(obj[arr[i]], arr[i], obj);
        }
    }
}

iterateObjectAlphabetically(obj, function(val, key, obj) {
    //do something here
});

फिर से, यह गारंटी देना चाहिए कि आप वर्णानुक्रम में पुनरावृति करें।

अंत में, इसे सरलतम तरीके से आगे ले जाते हुए, यह लाइब्रेरी आपके पास आने वाले किसी भी JSON को सॉर्ट करने के लिए पुनरावर्ती होगी: https://www.npmjs.com/package/json-stable-stringify

var stringify = require('json-stable-stringify');
var obj = { c: 8, b: [{z:6,y:5,x:4},7], a: 3 };
console.log(stringify(obj));

उत्पादन

{"a":3,"b":[{"x":4,"y":5,"z":6},7],"c":8}

9
यह बहुत ज्यादा है जो मैं बचने की कोशिश कर रहा था :) लेकिन धन्यवाद, भारी, समाधान की तरह सही लगता है।
इनोविन

1
इस कोड में एक बग है। आप obj[i]लूप के लिए संदर्भ नहीं दे सकते क्योंकि iएक पूर्णांक है, और संपत्ति के नाम आवश्यक नहीं हैं (इसलिए यह प्रश्न)। यह होना चाहिए obj[arr[i]]
एंड्रयू एन्सले

1
कॉलबैक एसिंक्रोनस व्यवहार के लिए अनन्य नहीं हैं।
markyzm

2
@ जोहान यहाँ एक कॉलबैक का उपयोग करके, वह iterateObjectAlphabeticallyएक पुन: प्रयोज्य कार्य में बदल जाता है। कॉलबैक के बिना 'पेलोड कोड' फ़ंक्शन के अंदर ही होगा। मुझे लगता है कि यह एक बहुत ही सुंदर समाधान है और एक जिसका उपयोग कई पुस्तकालयों और जेएस कोर में ही किया जाता है। जैसे Array.forEach
स्टिजन डे विट

1
@marksyzm यह ठीक है, मेरे मामले में मुझे केवल खेतों का चयन करना था। इस प्रकार, आपके उत्तर ने मुझे रास्ते में डाल दिया। धन्यवाद
Benj

39

मुझे लगता है कि यदि आप JSON पीढ़ी के नियंत्रण में हैं (और ऐसा लगता है जैसे आप हैं), तो आपके उद्देश्यों के लिए यह एक अच्छा समाधान हो सकता है: json-static-stringify

परियोजना की वेबसाइट से:

निर्धारक JSON.stringify () कड़े परिणामों से नियतात्मक हैश पाने के लिए कस्टम छँटाई के साथ

यदि JSON का उत्पादन नियतात्मक है तो आप इसे आसानी से अलग / विलय कर सकते हैं।


ध्यान दें कि रेपो खराब स्थिति में है: 3 वर्षों में अद्यतन नहीं किया गया है और इसमें अनसुलझे मुद्दे और पुल अनुरोध हैं। मुझे लगता है कि कुछ नए उत्तरों को देखना बेहतर है।
टॉम

3
@ टॉम यह भी ध्यान दें कि रेपो में 5 मिलियन साप्ताहिक (!) डाउनलोड हैं। दूसरे शब्दों में, इसका सक्रिय रूप से उपयोग किया जा रहा है। 'अनसुलझे' खुले मुद्दों और / या पुल अनुरोधों का अधिक मतलब नहीं है। बस इतना है कि लेखक (ओं) को उन मुद्दों की परवाह नहीं है या उनके पास कोई समय नहीं है। वास्तव में, इम्हो, सबसे अच्छे लिबास को अपडेट बहुत बार मिलता है। जब कुछ किया जाता है, तो यह किया जाता है। मैं यह नहीं कह रहा हूं कि इस परियोजना में कोई वास्तविक समस्या नहीं है, लेकिन यदि ऐसा है, तो कृपया उन बिंदुओं को इंगित करें। मेरा इस परिवाद BTW से कोई जुड़ाव नहीं है।
स्टिजन डे विट

ES6 मुझे लगता है कि यह निर्दिष्ट के अनुसार वस्तुओं (गैर-सरणियों) को सॉर्ट करने में सक्षम होने के कारण टूट गया। उपयोगकर्ता संपादन के लिए मुझे इसकी आवश्यकता है। भले ही कंप्यूटर के लिए ऑर्डर मायने नहीं रखता। यह उपयोगकर्ताओं को इसे संपादित करता है। यह कोशिश करने लायक था।
तमसुराजॉय

@Tom क्या कहता है के शीर्ष पर, मैं यह भी बताता हूं कि इस परियोजना की कोई रनटाइम निर्भरता नहीं है। मतलब कि अगर इस रेपो में कोई सुरक्षा / रखरखाव के मुद्दे नहीं हैं, तो यह शायद बहुत स्थिर और उपयोग करने के लिए सुरक्षित है। इसके अलावा, मैंने अभी इसे ES6 के साथ परीक्षण किया है और यह ठीक काम करने लगता है (फ़ायरफ़ॉक्स में कम से कम)।
फिल

27

आप संपत्ति के नामों के क्रमबद्ध सरणी को दूसरे तर्क के रूप में पास कर सकते हैं JSON.stringify():

JSON.stringify(obj, Object.keys(obj).sort())

1
क्या इस व्यवहार पर किसी प्रकार की प्रलेखित गारंटी है?
अमीर रीम

4
@richremer हां, ECMAScript मानक में , का दूसरा पैरामीटर JSON.stringify()कहा जाता है replacerऔर एक सरणी हो सकता है। इसका उपयोग उस निर्माण के लिए किया जाता है जिसका PropertyListउपयोग SerializeJSONObject()उस क्रम में गुणों को जोड़ने के लिए किया जाता है । यह ECMAScript 5 के बाद से प्रलेखित है
क्रिश्चियन डी'ह्योर्यूज

14
ध्यान दें कि अगर obj में ऑब्जेक्ट्स नेस्टेड हैं, नेस्टेड कुंजियों को दूसरे तर्क में भी मौजूद होना चाहिए; अन्यथा, उन्हें गिरा दिया जाएगा! प्रति-उदाहरण: > JSON.stringify({a: {c: 1, b: 2}}, ['a']) '{"a":{}}' सभी प्रासंगिक कुंजियों की सूची बनाने के लिए एक (हैकी) तरीका है कि वस्तु का पता लगाने के लिए JSON.stringify का उपयोग करें: function orderedStringify(obj) { const allKeys = []; JSON.stringify(obj, (k, v) => { allKeys.push(k); return v; }); return JSON.stringify(obj, allKeys.sort()); } उदाहरण:> orderedStringify({a: {c: 1, b: 2}}) '{"a":{"b":2,"c":1}}'
सैफ हकीम

Object.keys () पुनरावर्ती नहीं है । यह नेस्टेड एरेज़ या ऑब्जेक्ट्स वाली किसी भी ऑब्जेक्ट के लिए काम नहीं करेगा।
जोर

25

मुझे समझ में नहीं आ रहा है कि वर्तमान की सर्वोत्तम उत्तरों की जटिलता की आवश्यकता है, ताकि सभी कुंजियों को पुनः प्राप्त किया जा सके। जब तक पूर्ण प्रदर्शन की आवश्यकता नहीं होती है, यह मुझे लगता है कि हम सिर्फ JSON.stringify()दो बार कॉल कर सकते हैं , पहली बार सभी चाबियाँ प्राप्त करने के लिए, और दूसरी बार, वास्तव में काम करने के लिए। इस तरह, सभी पुनरावृत्ति जटिलता को नियंत्रित किया जाता है stringify, और हम जानते हैं कि यह अपना सामान जानता है, और प्रत्येक वस्तु को कैसे संभालना है:

function JSONstringifyOrder( obj, space )
{
    var allKeys = [];
    JSON.stringify( obj, function( key, value ){ allKeys.push( key ); return value; } )
    allKeys.sort();
    return JSON.stringify( obj, allKeys, space );
}

दिलचस्प है, लेकिन आप वास्तव में "धोखा" एक सरणी के लिए सभी कुंजी नक्शा करने के लिए stringify का उपयोग कर रहे हैं। उस सरणी को Object.keys
Z. Khullah

5
नहीं, बिंदु यह है कि Object.keys()पुनरावर्ती नहीं है, इसलिए यदि आपके पास कोई वस्तु है {a: "A", b: {c: "C"} }और आप उस पर Object.keys कहते हैं, तो आपको केवल चाबियाँ मिलेंगी aऔर b, लेकिन नहीं cJSON.stringifyJSON क्रमांकन प्रक्रिया द्वारा संभाला हर वस्तु प्रकार पर पुनरावृत्ति के बारे में सब कुछ जानता है, यह एक वस्तु की तरह है या एक सरणी (और यह पहले से ही दोनों को पहचानने के लिए तर्क को लागू करता है), इसलिए इसे हमारे लिए सब कुछ सही ढंग से संभालना चाहिए।
जोर

1
इस समाधान से प्यार करें, बहुत ही सुरुचिपूर्ण और सुरक्षित लगता है।
मार्कस

14

अपडेट 2018-7-24:

यह संस्करण नेस्टेड ऑब्जेक्ट्स को सॉर्ट करता है और सरणी को भी सपोर्ट करता है:

function sortObjByKey(value) {
  return (typeof value === 'object') ?
    (Array.isArray(value) ?
      value.map(sortObjByKey) :
      Object.keys(value).sort().reduce(
        (o, key) => {
          const v = value[key];
          o[key] = sortObjByKey(v);
          return o;
        }, {})
    ) :
    value;
}


function orderedJsonStringify(obj) {
  return JSON.stringify(sortObjByKey(obj));
}

परीक्षण का मामला:

  describe('orderedJsonStringify', () => {
    it('make properties in order', () => {
      const obj = {
        name: 'foo',
        arr: [
          { x: 1, y: 2 },
          { y: 4, x: 3 },
        ],
        value: { y: 2, x: 1, },
      };
      expect(orderedJsonStringify(obj))
        .to.equal('{"arr":[{"x":1,"y":2},{"x":3,"y":4}],"name":"foo","value":{"x":1,"y":2}}');
    });

    it('support array', () => {
      const obj = [
        { x: 1, y: 2 },
        { y: 4, x: 3 },
      ];
      expect(orderedJsonStringify(obj))
        .to.equal('[{"x":1,"y":2},{"x":3,"y":4}]');
    });

  });

पदावनत उत्तर:

ES2016 में संक्षिप्त संस्करण। Https://cackoverflow.com/a/29622653/94148 से @codename को क्रेडिट

function orderedJsonStringify(o) {
  return JSON.stringify(Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {}));
}

सिंटेक्स बिल्कुल सही नहीं है। होना चाहिए -function orderedJsonStringify(o) { return JSON.stringify(Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {})); }
बेन

अभी के लिए, इसने C # DataContractJsonSerializer और "__type" को जस स्ट्रिंग में पहले सूचीबद्ध नहीं किया गया है। धन्यवाद।
दही

2
ध्यान दें कि यह ईसाई के उत्तर की तरह, नेस्टेड वस्तुओं के साथ दुर्व्यवहार करता है।
डैनियल ग्रिसकॉम

SortObjPropertiesByKey परिभाषित नहीं है। क्या आप SortObjByKey का उपयोग करना चाहते थे?
पॉल लिंच

ऐसा नहीं लगता है कि यह sortObjByKey()परिपत्र संदर्भों के लिए जांच करता है, इसलिए सावधान रहें, यह इनपुट डेटा के आधार पर एक अनंत लूप में लटका सकता है। उदाहरण: var objA = {}; var objB = {objA: objA}; objA.objB = objB;-> sortObjByKey(objA);->VM59:6 Uncaught RangeError: Maximum call stack size exceeded
केलसुन


4

यह सतपाल सिंह के जवाब जैसा है

function stringifyJSON(obj){
    keys = [];
    if(obj){
        for(var key in obj){
            keys.push(key);
        }
    }
    keys.sort();
    var tObj = {};
    var key;
    for(var index in keys){
        key = keys[index];
        tObj[ key ] = obj[ key ];
    }
    return JSON.stringify(tObj);
}

obj1 = {}; obj1.os="linux"; obj1.name="X";
stringifyJSON(obj1); //returns "{"name":"X","os":"linux"}"

obj2 = {}; obj2.name="X"; obj2.os="linux";
stringifyJSON(obj2); //returns "{"name":"X","os":"linux"}"

3

आप एक कस्टम जोड़ सकते हैं toJSON अपने ऑब्जेक्ट में फ़ंक्शन जिसका उपयोग आप आउटपुट को अनुकूलित करने के लिए कर सकते हैं। फ़ंक्शन के अंदर, एक विशिष्ट क्रम में एक नई वस्तु में वर्तमान गुणों को जोड़ने पर उस आदेश को संरक्षित किया जाना चाहिए जब कड़ा हो।

यहाँ देखें:

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON/stringify

आदेश को नियंत्रित करने के लिए कोई अंतर्निहित पद्धति नहीं है क्योंकि JSON डेटा का उपयोग कुंजी द्वारा किया जाना है।

यहाँ एक छोटा उदाहरण के साथ एक jsfiddle है:

http://jsfiddle.net/Eq2Yw/

toJSONफ़ंक्शन को टिप्पणी करने का प्रयास करें - गुणों का क्रम उलट है। कृपया ध्यान रखें कि यह ब्राउज़र-विशिष्ट हो सकता है, अर्थात् विनिर्देश में आधिकारिक तौर पर आदेश देने का समर्थन नहीं किया गया है। यह फ़ायरफ़ॉक्स के वर्तमान संस्करण में काम करता है, लेकिन यदि आप 100% मजबूत समाधान चाहते हैं, तो आपको अपने स्वयं के स्ट्रिंगर फ़ंक्शन को लिखना पड़ सकता है।

संपादित करें:

स्ट्रिंग के गैर-नियतात्मक आउटपुट के बारे में एसओ का यह प्रश्न भी देखें, विशेष रूप से ब्राउज़र अंतर के बारे में डफ़ का विवरण:

कैसे निर्धारित करने के लिए कि एक JSON ऑब्जेक्ट को संशोधित नहीं किया गया है?


प्रत्येक ऑब्जेक्ट के गुणों को जाना जाता है (और ज्यादातर स्ट्रिंग्स) तो हार्डकॉडिंग मेरे अपने toJSON स्ट्रिंगर में गुणों को छांटने से ज्यादा तेज हो सकती है ...!
इन्नोविन

नीचे दिए गए 'orderJsonStringify' ने लगभग काम किया। लेकिन यह मेरे लिए एक बेहतर उपाय है। जब मुझे C # DataContractJsonSerializer का '__type' प्राप्त करने की आवश्यकता होती है, तो वह json string में पहला आइटम है। var json = JSON.stringify (myjsonobj, ['__type', 'id', 'text', 'somesubobj' etc .....]); सभी कुंजियों को सूचीबद्ध करने के लिए थोड़ा दर्द।
दही

3

एक पुनरावर्ती और सरलीकृत उत्तर:

function sortObject(obj) {
    if(typeof obj !== 'object')
        return obj
    var temp = {};
    var keys = [];
    for(var key in obj)
        keys.push(key);
    keys.sort();
    for(var index in keys)
        temp[keys[index]] = sortObject(obj[keys[index]]);       
    return temp;
}

var str = JSON.stringify(sortObject(obj), undefined, 4);

reorderइसका नाम बदल दिया जाना चाहिए sortObjectऔर यह सरणियों को नहीं संभालता है
जोनाथन गाव्रिच

यह देखने के लिए धन्यवाद, और ओपी का मुद्दा वस्तुओं का सहारा ले रहा था, न कि सरणियों का।
जेसन परम

@JonathanGawrych आप वैसे भी सरणियाँ क्यों छांटेंगे, उन्हें एक आदेश देना चाहिए। एक सरणी [1,2,3] एक सरणी [2,3,1] के समान नहीं है, लेकिन एक वस्तु का कोई संपत्ति क्रम नहीं है। समस्या यह है कि क्रम अचानक कठोरता के बाद मायने रखता है - 100% समतुल्य वस्तुओं के लिए तार अलग-अलग हो सकते हैं। दुर्भाग्य से एक नियतात्मक
स्ट्रिंग

1
@ मूर्रे - मुझे लगता है कि मैं पर्याप्त विशिष्ट नहीं था। द्वारा "सरणियों को संभाल नहीं करता है," मेरा मतलब था कि सरणियों को तोड़ दिया गया है, बिना छोड़ा नहीं। समस्या typeof arr === "object"यह है कि यह सरणियों को वस्तुओं में बदल देगा। उदाहरण के लिए var obj = {foo: ["bar", "baz"]}में stringified किया जाएगा{ "foo": { "0": "bar", "1": "baz"} }
जोनाथन Gawrych

@JonathanGawrych द्वारा पाई गई समस्या को ठीक करने के लिए:if(obj.constructor.prototype !== Object.prototype)
ricka

3

आप EcmaScript 2015 में संपत्ति के नाम से ऑब्जेक्ट को सॉर्ट कर सकते हैं

function sortObjectByPropertyName(obj) {
    return Object.keys(obj).sort().reduce((c, d) => (c[d] = obj[d], c), {});
}

शायद एक बेहतर नाम sortObjectPropertiesByName()या अधिक सरल होगा sortPropertiesByName()
Jan

3

मैंने @ जैसन परम से जवाब लिया और कुछ सुधार किए

function sortObject(obj, arraySorter) {
    if(typeof obj !== 'object')
        return obj
    if (Array.isArray(obj)) {
        if (arraySorter) {
            obj.sort(arraySorter);
        }
        for (var i = 0; i < obj.length; i++) {
            obj[i] = sortObject(obj[i], arraySorter);
        }
        return obj;
    }
    var temp = {};
    var keys = [];
    for(var key in obj)
        keys.push(key);
    keys.sort();
    for(var index in keys)
        temp[keys[index]] = sortObject(obj[keys[index]], arraySorter);       
    return temp;
}

यह ऑब्जेक्ट में कनवर्ट किए जा रहे सरणियों के मुद्दे को ठीक करता है, और यह आपको यह भी परिभाषित करने की अनुमति देता है कि सरणियों को कैसे सॉर्ट करना है।

उदाहरण:

var data = { content: [{id: 3}, {id: 1}, {id: 2}] };
sortObject(data, (i1, i2) => i1.id - i2.id)

उत्पादन:

{content:[{id:1},{id:2},{id:3}]}

2

स्वीकृत उत्तर किसी कारणवश नेस्टेड वस्तुओं के लिए मेरे लिए काम नहीं करता है। इसने मुझे अपना कोड अप करने के लिए प्रेरित किया। जैसा कि 2019 के अंत में जब मैं इसे लिखता हूं, तो भाषा के भीतर कुछ और विकल्प उपलब्ध होते हैं।

अद्यतन: मेरा मानना ​​है कि डेविड फर्लांग का उत्तर मेरे पहले प्रयास के लिए एक बेहतर दृष्टिकोण है, और मैं इससे दूर हो गया हूं। मेरा उद्देश्य Object.entries (...) के लिए समर्थन पर निर्भर करता है, इसलिए कोई इंटरनेट एक्सप्लोरर समर्थन नहीं करता है।

function normalize(sortingFunction) {
  return function(key, value) {
    if (typeof value === 'object' && !Array.isArray(value)) {
      return Object
        .entries(value)
        .sort(sortingFunction || undefined)
        .reduce((acc, entry) => {
          acc[entry[0]] = entry[1];
          return acc;
        }, {});
    }
    return value;
  }
}

JSON.stringify(obj, normalize(), 2);

-

व्यावसायिक संदर्भ के लिए इस संस्करण का उपयोग करना

मैंने पाया कि ऑब्जेक्ट में सभी कुंजियों का एक सरल, सपाट सरणी काम करेगा। लगभग सभी ब्राउज़रों में (एज या इंटरनेट एक्सप्लोरर नहीं, अनुमानित रूप से) और नोड 12+ में अब काफी कम समाधान है कि Array.prototype.flatMap (...) उपलब्ध है। (लॉश समतुल्य भी काम करेगा।) मैंने केवल सफारी, क्रोम, और फ़ायरफ़ॉक्स में परीक्षण किया है, लेकिन मुझे कोई कारण नहीं दिखता है कि यह कहीं और काम नहीं करेगा जो फ्लैट मैप और मानक JSON.stringify (...) का समर्थन करता है ।

function flattenEntries([key, value]) {
  return (typeof value !== 'object')
    ? [ [ key, value ] ]
    : [ [ key, value ], ...Object.entries(value).flatMap(flattenEntries) ];
}

function sortedStringify(obj, sorter, indent = 2) {
  const allEntries = Object.entries(obj).flatMap(flattenEntries);
  const sorted = allEntries.sort(sorter || undefined).map(entry => entry[0]);
  return JSON.stringify(obj, sorted, indent);
}

इसके साथ, आप बिना किसी तृतीय-पक्ष निर्भरता के स्ट्रिंग कर सकते हैं और यहां तक ​​कि कुंजी-मूल्य प्रविष्टि जोड़े पर सॉर्ट करने वाले अपने खुद के सॉर्ट एल्गोरिथ्म में पास कर सकते हैं, इसलिए आप कुंजी, पेलोड या दो के संयोजन से सॉर्ट कर सकते हैं। नेस्टेड ऑब्जेक्ट्स, सरणियों और सादे पुराने डेटा प्रकारों के किसी भी मिश्रण के लिए काम करता है।

const obj = {
  "c": {
    "z": 4,
    "x": 3,
    "y": [
      2048,
      1999,
      {
        "x": false,
        "g": "help",
        "f": 5
      }
    ]
  },
  "a": 2,
  "b": 1
};

console.log(sortedStringify(obj, null, 2));

प्रिंटों:

{
  "a": 2,
  "b": 1,
  "c": {
    "x": 3,
    "y": [
      2048,
      1999,
      {
        "f": 5,
        "g": "help",
        "x": false
      }
    ],
    "z": 4
  }
}

यदि आपके पास पुराने जावास्क्रिप्ट इंजन के साथ संगतता होनी चाहिए , तो आप इन थोड़े अधिक वर्बोज़ संस्करणों का उपयोग कर सकते हैं जो फ्लैटपाइप व्यवहार का अनुकरण करते हैं। क्लाइंट को कम से कम ES5 का समर्थन करना चाहिए, इसलिए कोई इंटरनेट एक्सप्लोरर 8 या उससे नीचे नहीं।

ये ऊपर के समान परिणाम लौटाएंगे।

function flattenEntries([key, value]) {
  if (typeof value !== 'object') {
    return [ [ key, value ] ];
  }
  const nestedEntries = Object
    .entries(value)
    .map(flattenEntries)
    .reduce((acc, arr) => acc.concat(arr), []);
  nestedEntries.unshift([ key, value ]);
  return nestedEntries;
}

function sortedStringify(obj, sorter, indent = 2) {
  const sortedKeys = Object
    .entries(obj)
    .map(flattenEntries)
    .reduce((acc, arr) => acc.concat(arr), [])
    .sort(sorter || undefined)
    .map(entry => entry[0]);
  return JSON.stringify(obj, sortedKeys, indent);
}

1

दर्ज करें, नेस्टेड ऑब्जेक्ट्स, ऑब्जेक्ट विशेषता के किसी भी मूल्य के साथ काम करता है:

function sort(myObj) {
  var sortedObj = {};
  Object.keys(myObj).sort().forEach(key => {
    sortedObj[key] = _.isPlainObject(myObj[key]) ? sort(myObj[key]) : myObj[key]
  })
  return sortedObj;
}
JSON.stringify(sort(yourObj), null, 2)

यह क्रोम और नोड के व्यवहार पर निर्भर करता है कि किसी ऑब्जेक्ट को सौंपी गई पहली कुंजी को पहले आउटपुट किया जाए JSON.stringify


2
धन्यवाद, लेकिन मुझे 4 साल पहले यह समस्या थी, मुझे यह कहने में खुशी हो रही है कि मैं तब से थोड़ा आगे बढ़ गया हूं :)
इनोवेटिन

1
:) यह सुनकर अच्छा लगा। हालांकि मुझे कल यह समस्या थी और मुझे आपके (पुराने लेकिन अभी भी प्रासंगिक) प्रश्न के तहत जो उत्तर मिल रहा था वह नहीं मिला :)
AJP

0

प्रयत्न:

function obj(){
  this.name = '';
  this.os = '';
}

a = new obj();
a.name = 'X',
a.os = 'linux';
JSON.stringify(a);
b = new obj();
b.os = 'linux';
b.name = 'X',
JSON.stringify(b);

धन्यवाद, लेकिन स्पष्ट रूप से आदेश अपरिभाषित है और केवल काम करने के लिए होता है। दिलचस्प दृष्टिकोण हालांकि!
इनोविन

0

मैंने ऑब्जेक्ट को सॉर्ट करने के लिए एक फ़ंक्शन बनाया, और कॉलबैक के साथ .. जो वास्तव में एक नई ऑब्जेक्ट बनाता है

function sortObj( obj , callback ) {

    var r = [] ;

    for ( var i in obj ){
        if ( obj.hasOwnProperty( i ) ) {
             r.push( { key: i , value : obj[i] } );
        }
    }

    return r.sort( callback ).reduce( function( obj , n ){
        obj[ n.key ] = n.value ;
        return obj;
    },{});
}

और इसे ऑब्जेक्ट के साथ कॉल करें।

var obj = {
    name : "anu",
    os : "windows",
    value : 'msio',
};

var result = sortObj( obj , function( a, b ){
    return a.key < b.key  ;    
});

JSON.stringify( result )

जो प्रिंट करता है {"value":"msio","os":"windows","name":"anu"}, और मूल्य के साथ छंटाई के लिए।

var result = sortObj( obj , function( a, b ){
    return a.value < b.value  ;    
});

JSON.stringify( result )

जो प्रिंट करता है {"os":"windows","value":"msio","name":"anu"}


1
अच्छी तरह से काम करता है, लेकिन दुर्भाग्य से यह पुनरावर्ती नहीं है।
जोनाथन गवरीच

0

यदि सूची में ऑब्जेक्ट्स में समान गुण नहीं हैं, तो स्ट्रिंग करने से पहले एक संयुक्त मास्टर ऑब्जेक्ट बनाएं:

let arr=[ <object1>, <object2>, ... ]
let o = {}
for ( let i = 0; i < arr.length; i++ ) {
  Object.assign( o, arr[i] );
}
JSON.stringify( arr, Object.keys( o ).sort() );


0
function FlatternInSort( obj ) {
    if( typeof obj === 'object' )
    {
        if( obj.constructor === Object )
        {       //here use underscore.js
            let PaireStr = _( obj ).chain().pairs().sortBy( p => p[0] ).map( p => p.map( FlatternInSort ).join( ':' )).value().join( ',' );
            return '{' + PaireStr + '}';
        }
        return '[' + obj.map( FlatternInSort ).join( ',' ) + ']';
    }
    return JSON.stringify( obj );
}

// उदाहरण नीचे। प्रत्येक परत में, {} जैसी वस्तुओं के लिए, कुंजी क्रम में चपटा हुआ। सरणियों, संख्याओं या तारों के लिए, JSON.stringify के साथ / जैसे चपटा।

FlatternInSort ({c: 9, b: {y: 4, z: 2, e: 9}, F: 4, a: [{j: 8, h: 3}, {a: 3, b: 7}] })

"{" एफ ": 4," एक ": [{" h ": 3," j ": 8}, {" एक ": 3," बी ": 7}]," ख ": {" ई " : 9, "y": 4, "Z": 2}, "सी": 9} "


कृपया यह बताएं कि बाहरी परिवाद का उपयोग क्यों किया गया है, और जैसा @DeKaNszn ने कहा, कुछ स्पष्टीकरण और एक परिचय जोड़ें। सराहना की जाएगी।
बेंज

इस funtion की प्रतिलिपि मेरे प्रोजेक्ट से मिली है। जिसमें मैं underscore.js का उपयोग करता हूं।
संततुर

0

AJP के उत्तर का विस्तार, सरणियों को संभालने के लिए:

function sort(myObj) {
    var sortedObj = {};
    Object.keys(myObj).sort().forEach(key => {
        sortedObj[key] = _.isPlainObject(myObj[key]) ? sort(myObj[key]) : _.isArray(myObj[key])? myObj[key].map(sort) : myObj[key]
    })
    return sortedObj;
}

0

हैरानी की बात है किसी ने भी लश के isEqualसमारोह का उल्लेख नहीं किया ।

यह निर्धारित करने के लिए दो मूल्यों के बीच एक गहरी तुलना करता है कि क्या वे समकक्ष हैं।

नोट: यह विधि सरणियों, सरणी बफ़र्स, बूलियन, दिनांक ऑब्जेक्ट, त्रुटि ऑब्जेक्ट, मैप, संख्या, ऑब्जेक्ट ऑब्जेक्ट, regexes, सेट, स्ट्रिंग्स, प्रतीकों और टाइप किए गए सरणियों की तुलना करने का समर्थन करती है। ऑब्जेक्ट ऑब्जेक्ट्स की तुलना उनके स्वयं के द्वारा की जाती है, न कि विरासत में मिलने वाली, असंख्य गुणों से। फ़ंक्शंस और DOM नोड्स की तुलना सख्त समानता, यानी === से की जाती है।

https://lodash.com/docs/4.17.11#isEqual

मूल समस्या के साथ - कुंजी को असंगत रूप से आदेश दिया गया है - यह एक महान समाधान है - और निश्चित रूप से यह बंद हो जाएगा यदि यह पूरे ऑब्जेक्ट को नेत्रहीन रूप से अनुक्रमित करने के बजाय एक संघर्ष पाता है।

ऐसा करने वाले संपूर्ण पुस्तकालय को आयात करने से बचने के लिए:

import { isEqual } from "lodash-es";

बोनस उदाहरण: आप इस कस्टम ऑपरेटर के साथ RxJS के साथ भी इसका उपयोग कर सकते हैं

export const distinctUntilEqualChanged = <T>(): MonoTypeOperatorFunction<T> => 
                                                pipe(distinctUntilChanged(isEqual));

0

आखिरकार, यह एक एरे की जरूरत है जो नेस्टेड ऑब्जेक्ट में सभी कुंजियों को कैश करता है (अन्यथा यह बिना पड़ी चाबियों को छोड़ देगा।) सबसे पुराना उत्तर सिर्फ सादा गलत है, क्योंकि दूसरा तर्क डॉट-नोटेशन की परवाह नहीं करता है। तो, उत्तर (सेट का उपयोग करके) बन जाता है।

function stableStringify (obj) {
  const keys = new Set()
  const getAndSortKeys = (a) => {
    if (a) {
      if (typeof a === 'object' && a.toString() === '[object Object]') {
        Object.keys(a).map((k) => {
          keys.add(k)
          getAndSortKeys(a[k])
        })
      } else if (Array.isArray(a)) {
        a.map((el) => getAndSortKeys(el))
      }
    }
  }
  getAndSortKeys(obj)
  return JSON.stringify(obj, Array.from(keys).sort())
}

0

यहाँ एक क्लोन दृष्टिकोण है ... इस ऑब्जेक्ट को क्लोन करने से पहले जोंस में परिवर्तित किया जाता है:

function sort(o: any): any {
    if (null === o) return o;
    if (undefined === o) return o;
    if (typeof o !== "object") return o;
    if (Array.isArray(o)) {
        return o.map((item) => sort(item));
    }
    const keys = Object.keys(o).sort();
    const result = <any>{};
    keys.forEach((k) => (result[k] = sort(o[k])));
    return result;
}

अगर बहुत नया है, लेकिन पैकेज पर काम करने के लिए लगता है। फ़ाइल ठीक है।


-3

ऐसी Array.sortविधि है जो आपके लिए सहायक हो सकती है। उदाहरण के लिए:

yourBigArray.sort(function(a,b){
    //custom sorting mechanism
});

1
हालांकि मैं सरणी को क्रमबद्ध नहीं करना चाहता। वास्तव में सरणी भाग महत्वपूर्ण नहीं है .. मैं किसी वस्तु के गुणों को क्रमबद्ध करना चाहता हूं .. कुछ त्वरित प्रयोगों से ऐसा लगता है जैसे गुणों को उस क्रम में सूचीबद्ध किया गया है जो वे बनाए गए हैं। एक तरह से एक नई वस्तु बनाने और वर्णमाला के क्रम में गुणों की प्रतिलिपि बनाने के लिए हो सकता है, लेकिन मैं उम्मीद कर रहा हूं कि कुछ आसान / तेज है ..
इनोविन

1
@Innovine, यहां तक ​​कि कि चाबियाँ के रूप में काम करने की गारंटी नहीं है कल्पना द्वारा निर्माण समय से आदेश नहीं दिया जाएगा।
डॉगबर्ट

फिर सवाल यह हो जाता है कि मैं अपनी वस्तुओं को इस तरह से कैसे कड़ा करूं कि चाबी एक निश्चित क्रम में हो .. मेरे लिए ऐसा करना असंभव नहीं है (obj में कुंजी) और उन्हें एक अस्थायी सरणी में संग्रहीत करें और उस तरह से मैन्युअल रूप से संग्रहीत करें एक स्ट्रिंग का निर्माण .. लेकिन मैं सख्त उम्मीद कर रहा हूं कि एक आसान तरीका है
इनोविन

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