मैं नेस्टेड ऑब्जेक्ट्स, एरेज़ या JSON तक कैसे पहुंच और प्रोसेस कर सकता हूं?


874

मेरे पास एक नेस्टेड डेटा संरचना है जिसमें ऑब्जेक्ट और सरणियाँ हैं। मैं जानकारी कैसे निकाल सकता हूं, अर्थात किसी विशिष्ट या कई मानों (या कुंजियों) का उपयोग कर सकता हूं?

उदाहरण के लिए:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

मैं nameदूसरे आइटम में कैसे पहुंच सकता हूं items?


22
@ मार्सेल: इसे "मुझे डेटा नेस्टेड डेटा संरचना या JSON के रूप में पढ़ा जाना है , मैं एक विशिष्ट मूल्य कैसे प्राप्त कर सकता हूं?" मुझे अंतर पता है, लेकिन बहुत से लोग "ऑब्जेक्ट" के बजाय "JSON" की खोज नहीं कर सकते हैं। कई सवाल वास्तव में "मैं इस JSON में एक्स का उपयोग कैसे कर सकता हूं" फॉर्म के हैं। एकमात्र स्थान जहां मैं अपने उत्तर में JSON का उल्लेख करता हूं, जहां मैं समझाता हूं कि यह क्या है। यदि आपके पास एक सुझाव है कि इसे बेहतर तरीके से कैसे संवाद किया जाए, तो मैं सभी कान हूं।
फेलिक्स क्लिंग

जवाबों:


1159

प्रारंभिक

जावास्क्रिप्ट में केवल एक डेटा प्रकार होता है जिसमें कई मान हो सकते हैं: ऑब्जेक्ट । एक ऐरे वस्तु का एक विशेष रूप है।

(सादा) वस्तुओं का रूप होता है

{key: value, key: value, ...}

अर्र्स का रूप है

[value, value, ...]

दोनों सरणियाँ और ऑब्जेक्ट एक key -> valueसंरचना को उजागर करते हैं। किसी सरणी में कुंजियां संख्यात्मक होनी चाहिए, जबकि किसी भी स्ट्रिंग का उपयोग ऑब्जेक्ट में कुंजी के रूप में किया जा सकता है। कुंजी-मूल्य जोड़े को "गुण" भी कहा जाता है ।

संपत्तियों को या तो डॉट नोटेशन का उपयोग करके एक्सेस किया जा सकता है

const value = obj.someProperty;

या ब्रैकेट संकेतन , अगर संपत्ति का नाम मान्य जावास्क्रिप्ट पहचानकर्ता नाम नहीं होगा [कल्पना] , या नाम एक चर का मूल्य है:

// the space is not a valid character in identifier names
const value = obj["some Property"];

// property name as variable
const name = "some Property";
const value = obj[name];

उस कारण से, सरणी तत्वों को केवल ब्रैकेट नोटेशन का उपयोग करके एक्सेस किया जा सकता है:

const value = arr[5]; // arr.5 would be a syntax error

// property name / index as variable
const x = 5;
const value = arr[x];

रुको ... JSON के बारे में क्या?

JSON XML, YAML, CSV और अन्य की तरह डेटा का एक पाठीय प्रतिनिधित्व है। इस तरह के डेटा के साथ काम करने के लिए, इसे पहले जावास्क्रिप्ट डेटा प्रकारों, यानी सरणियों और वस्तुओं में बदलना होगा (और उन लोगों के साथ कैसे काम करना है, यह अभी समझाया गया है)। पार्स JSON के जावास्क्रिप्ट में JSON को कैसे समझा जाए ?

आगे पढ़ने की सामग्री

सरणियों और वस्तुओं तक कैसे पहुंचा जाए, यह मूलभूत जावास्क्रिप्ट ज्ञान है और इसलिए एमडीएन जावास्क्रिप्ट गाइड , विशेषकर वर्गों को पढ़ना उचित है



नेस्टेड डेटा संरचनाओं तक पहुँचना

एक नेस्टेड डेटा संरचना एक सरणी या ऑब्जेक्ट है जो अन्य सरणियों या वस्तुओं को संदर्भित करता है, अर्थात इसके मान सरणियाँ या ऑब्जेक्ट हैं। इस तरह के ढांचे को लगातार डॉट या ब्रैकेट अंकन द्वारा पहुँचा जा सकता है।

यहाँ एक उदाहरण है:

const data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

चलो मान लेते हैं कि हम nameदूसरी वस्तु तक पहुंचना चाहते हैं ।

यहाँ हम इसे चरण-दर-चरण कैसे कर सकते हैं:

जैसा कि हम देख सकते हैं dataकि एक ऑब्जेक्ट है, इसलिए हम डॉट नोटेशन का उपयोग करके इसके गुणों तक पहुंच सकते हैं। itemsसंपत्ति के रूप में निम्नानुसार पहुंचा जा सकता है:

data.items

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

data.items[1]

यह मान एक वस्तु है और हम nameसंपत्ति तक पहुंचने के लिए फिर से डॉट नोटेशन का उपयोग करते हैं। तो हम अंततः प्राप्त करते हैं:

const item_name = data.items[1].name;

वैकल्पिक रूप से, हम किसी भी गुण के लिए ब्रैकेट नोटेशन का उपयोग कर सकते थे, खासकर अगर नाम में ऐसे अक्षर शामिल थे जो इसे डॉट नोटेशन उपयोग के लिए अमान्य बना देते थे:

const item_name = data['items'][1]['name'];

मैं एक संपत्ति का उपयोग करने की कोशिश कर रहा हूं, लेकिन मुझे केवल undefinedवापस मिलेगा ?

जब आप प्राप्त कर रहे होते हैं undefined, तो अधिकांश वस्तु / सरणी में बस उस नाम की कोई संपत्ति नहीं होती है।

const foo = {bar: {baz: 42}};
console.log(foo.baz); // undefined

ऑब्जेक्ट / सरणी की संरचना का उपयोग करें console.logया console.dirनिरीक्षण करें। आप जिस संपत्ति तक पहुंचने की कोशिश कर रहे हैं, वह वास्तव में एक नेस्टेड ऑब्जेक्ट / सरणी पर परिभाषित हो सकती है।

console.log(foo.bar.baz); // 42

क्या होगा यदि संपत्ति के नाम गतिशील हैं और मैं उन्हें पहले से नहीं जानता हूं?

संपत्ति के नाम अज्ञात हैं या हम एक वस्तु के सभी गुण का उपयोग करना चाहते हैं / एक सरणी के तत्वों, हम उपयोग कर सकते हैं for...in [MDN] वस्तुओं के लिए लूप और for [MDN] सभी गुण / तत्वों पर पुनरावृति करने सरणियों के लिए पाश।

वस्तुओं

के सभी गुणों पर पुनरावृति करने के लिए data, हम इस तरह से ऑब्जेक्ट पर पुनरावृति कर सकते हैं :

for (const prop in data) {
    // `prop` contains the name of each property, i.e. `'code'` or `'items'`
    // consequently, `data[prop]` refers to the value of each property, i.e.
    // either `42` or the array
}

ऑब्जेक्ट कहाँ से आता है (और आप क्या करना चाहते हैं) पर निर्भर करते हुए, आपको प्रत्येक पुनरावृत्ति में परीक्षण करना पड़ सकता है कि क्या संपत्ति वास्तव में ऑब्जेक्ट की संपत्ति है, या यह एक विरासत में मिली संपत्ति है। आप इसे Object#hasOwnProperty [एमडीएन] के साथ कर सकते हैं ।

करने के लिए विकल्प के रूप में for...inके साथ hasOwnProperty, आप उपयोग कर सकते हैं Object.keys [MDN] एक पाने के लिए संपत्ति के नाम की सरणी :

Object.keys(data).forEach(function(prop) {
  // `prop` is the property name
  // `data[prop]` is the property value
});

Arrays

data.items सरणी के सभी तत्वों पर पुनरावृति करने के लिए , हम एक forलूप का उपयोग करते हैं :

for(let i = 0, l = data.items.length; i < l; i++) {
    // `i` will take on the values `0`, `1`, `2`,..., i.e. in each iteration
    // we can access the next element in the array with `data.items[i]`, example:
    // 
    // var obj = data.items[i];
    // 
    // Since each element is an object (in our example),
    // we can now access the objects properties with `obj.id` and `obj.name`. 
    // We could also use `data.items[i].id`.
}

कोई भी for...inसरणियों पर पुनरावृत्त करने के लिए उपयोग कर सकता है , लेकिन ऐसे कारण हैं जिनसे इसे बचा जाना चाहिए: जावास्क्रिप्ट में बुरे व्यवहार पर विचार करने वाले सरणियों के साथ 'फॉर (लिस्ट में var आइटम) क्यों है?

ECMAScript 5 के बढ़ते ब्राउज़र समर्थन के साथ, सरणी विधि forEach [MDN] एक दिलचस्प विकल्प भी बन जाती है:

data.items.forEach(function(value, index, array) {
    // The callback is executed for each element in the array.
    // `value` is the element itself (equivalent to `array[index]`)
    // `index` will be the index of the element in the array
    // `array` is a reference to the array itself (i.e. `data.items` in this case)
}); 

ES2015 (ES6) का समर्थन करने वाले वातावरण में, आप [MDN] लूप का उपयोग कर सकते हैं , जो न केवल सरणियों के लिए काम करता है, बल्कि किसी भी चलने योग्य के लिए :for...of

for (const item of data.items) {
   // `item` is the array element, **not** the index
}

प्रत्येक पुनरावृत्ति में, for...ofसीधे हमें पुनरावृत्ति का अगला तत्व देता है, उपयोग या उपयोग करने के लिए कोई "सूचकांक" नहीं है।


क्या होगा यदि डेटा संरचना की "गहराई" मेरे लिए अज्ञात है?

अज्ञात कुंजियों के अलावा, डेटा संरचना की "गहराई" (अर्थात कितनी नेस्टेड ऑब्जेक्ट) है, यह अज्ञात भी हो सकता है। गहरी नेस्टेड गुणों तक कैसे पहुंचें, आमतौर पर सटीक डेटा संरचना पर निर्भर करता है।

लेकिन अगर डेटा संरचना में दोहराए जाने वाले पैटर्न होते हैं, उदाहरण के लिए, एक बाइनरी ट्री का प्रतिनिधित्व, समाधान में आमतौर पर डेटा संरचना के प्रत्येक स्तर तक पुनरावर्ती [विकिपीडिया] का उपयोग शामिल है।

एक बाइनरी ट्री का पहला लीफ नोड प्राप्त करने के लिए यहां एक उदाहरण दिया गया है:

function getLeaf(node) {
    if (node.leftChild) {
        return getLeaf(node.leftChild); // <- recursive call
    }
    else if (node.rightChild) {
        return getLeaf(node.rightChild); // <- recursive call
    }
    else { // node must be a leaf node
        return node;
    }
}

const first_leaf = getLeaf(root);

अज्ञात कुंजी और गहराई के साथ नेस्टेड डेटा संरचना तक पहुंचने के लिए एक अधिक सामान्य तरीका मूल्य के प्रकार का परीक्षण करना और तदनुसार कार्य करना है।

यहां एक उदाहरण है जो किसी नेस्टेड डेटा संरचना के अंदर सभी आदिम मूल्यों को एक सरणी में जोड़ता है (यह मानते हुए कि इसमें कोई फ़ंक्शन नहीं है)। यदि हम एक वस्तु (या सरणी) का सामना करते हैं तो हम बस toArrayउस मूल्य (पुनरावर्ती कॉल) पर फिर से कॉल करते हैं।

function toArray(obj) {
    const result = [];
    for (const prop in obj) {
        const value = obj[prop];
        if (typeof value === 'object') {
            result.push(toArray(value)); // <- recursive call
        }
        else {
            result.push(value);
        }
    }
    return result;
}



सहायकों

चूंकि एक जटिल वस्तु या सरणी की संरचना आवश्यक रूप से स्पष्ट नहीं है, हम आगे बढ़ने के तरीके के बारे में निर्णय करने के लिए प्रत्येक चरण में मूल्य का निरीक्षण कर सकते हैं। console.log [एमडीएन] और console.dir [एमडीएन] हमें ऐसा करने में मदद करते हैं। उदाहरण के लिए (क्रोम कंसोल का आउटपुट):

> console.log(data.items)
 [ Object, Object ]

यहाँ हम देखते हैं कि data.itemsदो तत्वों के साथ एक सरणी है जो दोनों वस्तुएं हैं। क्रोम कंसोल में ऑब्जेक्ट्स का विस्तार और निरीक्षण भी तुरंत किया जा सकता है।

> console.log(data.items[1])
  Object
     id: 2
     name: "bar"
     __proto__: Object

यह हमें बताता है कि data.items[1]एक वस्तु है, और इसे विस्तारित करने के बाद हम देखते हैं कि इसमें तीन गुण हैं id, nameऔर __proto__। उत्तरार्द्ध एक आंतरिक संपत्ति है जिसका उपयोग ऑब्जेक्ट की प्रोटोटाइप श्रृंखला के लिए किया जाता है। प्रोटोटाइप श्रृंखला और विरासत इस जवाब के लिए गुंजाइश से बाहर है, हालांकि।


3
यहां जो कुछ लिंक किया जा रहा है, वह वास्तव में पूछ रहा है कि यह jQuery में कैसे किया जाए, जो कि निष्पक्ष होना यहां 1 या 2 चीजों को सरल बनाता है। यह निश्चित नहीं है कि इसे मेगापोस्ट के अधिक से अधिक बनाया जाए या उन लोगों को अलग से उत्तर दिया जाए - यहां जो मूल बातें हैं, वह एक ऐसी वस्तु है जो एक सरणी है जो आमतौर पर एक चीज होती है जो वास्तव में पूछी जा रही है ...।
क्रिस Moschini

1
@ फेलिक्स-क्लिंग एक बात ... नेस्टेड ऑब्जेक्ट्स के साथ, जैसे let object = {a: 1, b: 2, c: { a: 3, b: 4 }};, यह प्रत्येक नेस्टेड ऑब्जेक्ट के लिए एक सरणी युक्त एक सरणी देता है, इस मामले [ 1, 2, [ 3, 4 ] ]में पुश के बजाय पुनरावर्ती कॉल में कॉनैट का उपयोग करना बेहतर नहीं होगा? (
परस्पर

3
यह सबसे अधिक गहराई से उत्तर है जो मैंने कभी स्टैक ओवरफ्लो पर देखा है - और इसने मेरे प्रश्न का उत्तर दिया! धन्यवाद!
विलियम जोन्स

इस एक पृष्ठ ने मुझे ARRAY और OBJ
4ni5

76

आप इसे इस तरह एक्सेस कर सकते हैं

data.items[1].name

या

data["items"][1]["name"]

दोनों तरीके बराबर हैं।


हाँ, लेकिन आप डेटा ["आइटम"] नहीं कर सकते। 1.name
neaumusic

5
पहले कहीं अधिक सहज, पठनीय और छोटा है;) मैं ब्रैकेट प्रॉपर्टी सिंटैक्स का उपयोग करना पसंद करता हूं, जब प्रॉपर्टी का नाम परिवर्तनशील होता है।
डांटे.स्मिथ

35

मामले में आप एक का उपयोग करने की कोशिश कर रहे हैं itemद्वारा उदाहरण संरचना से idया nameसरणी, इसका इस्तेमाल किया जाएगा सबसे आसान तरीका में यह की स्थिति जानने के बिना, Underscore.js पुस्तकालय:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

_.find(data.items, function(item) {
  return item.id === 2;
});
// Object {id: 2, name: "bar"}

मेरे अनुभव से, कोड forया for..inपरिणाम के बजाय उच्च आदेश कार्यों का उपयोग करने से कोड में परिणाम होता है, और इसलिए अधिक बनाए रखने के लिए आसान है।

बस मेरे 2 सेंट।


29

ऑब्जेक्ट्स और एरेज़ में बहुत सारे बिल्ट-इन तरीके हैं जो आपको प्रोसेसिंग डेटा के साथ मदद कर सकते हैं।

नोट: कई उदाहरणों में मैं तीर के कार्यों का उपयोग कर रहा हूं । वे फ़ंक्शन अभिव्यक्तियों के समान हैं , लेकिन वे thisमूल्य को शाब्दिक रूप से बांधते हैं ।

Object.keys(), Object.values()(ES 2017) और Object.entries()(ES 2017)

Object.keys()ऑब्जेक्ट की कुंजियों का Object.values()एक सरणी देता है , ऑब्जेक्ट के मानों की Object.entries()एक सरणी लौटाता है , और एक प्रारूप में ऑब्जेक्ट की कुंजी और संबंधित मानों की एक सरणी देता है [key, value]

const obj = {
  a: 1
 ,b: 2
 ,c: 3
}

console.log(Object.keys(obj)) // ['a', 'b', 'c']
console.log(Object.values(obj)) // [1, 2, 3]
console.log(Object.entries(obj)) // [['a', 1], ['b', 2], ['c', 3]]

Object.entries() लूप के लिए और विनाशकारी असाइनमेंट के साथ

const obj = {
  a: 1
 ,b: 2
 ,c: 3
}

for (const [key, value] of Object.entries(obj)) {
  console.log(`key: ${key}, value: ${value}`)
}

यह का परिणाम पुनरावृति करने के लिए बहुत सुविधाजनक है Object.entries()एक साथ के लिए-पाश और destructuring काम

के लिए-पाश की मदद से आप सरणी तत्व पुनरावृति। वाक्यविन्यास है for (const element of array)(हम के constसाथ बदल सकते हैं varया let, लेकिन constअगर हम संशोधित करने का इरादा नहीं रखते हैं तो इसका उपयोग करना बेहतर है element)।

विनाशकारी असाइनमेंट आपको किसी सरणी या किसी ऑब्जेक्ट से मान निकालने देता है और उन्हें वेरिएबल्स में असाइन करता है। इस मामले में const [key, value]इसका मतलब है कि हम [key, value]सरणी को असाइन करने के बजाय, उस सरणी elementके पहले तत्व को keyऔर दूसरे तत्व को असाइन करते हैं value। यह इस के बराबर है:

for (const element of Object.entries(obj)) {
  const key = element[0]
       ,value = element[1]
}

जैसा कि आप देख सकते हैं, विनाशकारी इसे बहुत सरल बनाता है।

Array.prototype.every() तथा Array.prototype.some()

every()विधि रिटर्न trueनिर्दिष्ट कॉलबैक फ़ंक्शन रिटर्न अगर trueके लिए हर सरणी के तत्व। some()विधि रिटर्न trueअगर निर्दिष्ट कॉलबैक फ़ंक्शन रिटर्न trueके लिए कुछ (कम से कम एक) तत्व।

const arr = [1, 2, 3]

// true, because every element is greater than 0
console.log(arr.every(x => x > 0))
// false, because 3^2 is greater than 5
console.log(arr.every(x => Math.pow(x, 2) < 5))
// true, because 2 is even (the remainder from dividing by 2 is 0)
console.log(arr.some(x => x % 2 === 0))
// false, because none of the elements is equal to 5
console.log(arr.some(x => x === 5))

Array.prototype.find() तथा Array.prototype.filter()

find()तरीकों रिटर्न पहला तत्व है जो संतुष्ट प्रदान की कॉलबैक फ़ंक्शन। filter()विधि की एक सरणी देता है सभी तत्व है जो संतुष्ट प्रदान की कॉलबैक फ़ंक्शन।

const arr = [1, 2, 3]

// 2, because 2^2 !== 2
console.log(arr.find(x => x !== Math.pow(x, 2)))
// 1, because it's the first element
console.log(arr.find(x => true))
// undefined, because none of the elements equals 7
console.log(arr.find(x => x === 7))

// [2, 3], because these elements are greater than 1
console.log(arr.filter(x => x > 1))
// [1, 2, 3], because the function returns true for all elements
console.log(arr.filter(x => true))
// [], because none of the elements equals neither 6 nor 7
console.log(arr.filter(x => x === 6 || x === 7))

Array.prototype.map()

map()विधि सरणी तत्वों पर एक प्रदान की कॉलबैक फ़ंक्शन को कॉल के परिणामों के साथ एक सरणी देता है।

const arr = [1, 2, 3]

console.log(arr.map(x => x + 1)) // [2, 3, 4]
console.log(arr.map(x => String.fromCharCode(96 + x))) // ['a', 'b', 'c']
console.log(arr.map(x => x)) // [1, 2, 3] (no-op)
console.log(arr.map(x => Math.pow(x, 2))) // [1, 4, 9]
console.log(arr.map(String)) // ['1', '2', '3']

Array.prototype.reduce()

reduce()विधि दो तत्वों के साथ प्रदान की कॉलबैक फ़ंक्शन को फोन करके किसी एकल मान के लिए एक सरणी कम कर देता है।

const arr = [1, 2, 3]

// Sum of array elements.
console.log(arr.reduce((a, b) => a + b)) // 6
// The largest number in the array.
console.log(arr.reduce((a, b) => a > b ? a : b)) // 3

reduce()विधि एक वैकल्पिक दूसरा पैरामीटर, जो प्रारंभिक मूल्य है लेता है। यह उपयोगी है जब आप जिस सरणी पर कॉल करते reduce()हैं उसमें शून्य या एक तत्व हो सकते हैं। उदाहरण के लिए, यदि हम एक ऐसा फंक्शन बनाना चाहते हैं, sum()जो एक तर्क के रूप में एक सरणी लेता है और सभी तत्वों का योग लौटाता है, तो हम इसे इस तरह लिख सकते हैं:

const sum = arr => arr.reduce((a, b) => a + b, 0)

console.log(sum([]))     // 0
console.log(sum([4]))    // 4
console.log(sum([2, 5])) // 7


यह मेरा पसंदीदा उत्तर है। आप लूप के लिए एक उदाहरण भी जोड़ सकते हैं, बस एक निष्कासित नेस्टेड डेटा, जैसेObject.keys(data["items"]).forEach(function(key) { console.log(data["items"][key].id); console.log(data["items"][key].name); });
सिल्वरसर्फर

25

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

var obj = { hello: "world" };
var key = "hello";
alert(obj[key]);//world

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

संपत्ति एक्सेस किए जा रहे पहले से ही जाना जाता है, लेकिन पथ इस वस्तु में जटिल है, उदाहरण के लिए, तो

var obj = {
 arr: [
    { id: 1, name: "larry" },    
    { id: 2, name: "curly" },
    { id: 3, name: "moe" }
 ]
};

और आप जानते हैं कि आप ऑब्जेक्ट में सरणी का पहला परिणाम प्राप्त करना चाहते हैं, शायद आप उपयोग करना चाहते हैं

var moe = obj["arr[0].name"];

हालांकि, कि एक अपवाद का कारण होगा के रूप में वहाँ है कि नाम के साथ वस्तु की कोई संपत्ति है। इसका उपयोग करने में सक्षम वस्तु का पेड़ पहलू को समतल करना होगा। यह पुनरावर्ती किया जा सकता है।

function flatten(obj){
 var root = {};
 (function tree(obj, index){
   var suffix = toString.call(obj) == "[object Array]" ? "]" : "";
   for(var key in obj){
    if(!obj.hasOwnProperty(key))continue;
    root[index+key+suffix] = obj[key];
    if( toString.call(obj[key]) == "[object Array]" )tree(obj[key],index+key+suffix+"[");
    if( toString.call(obj[key]) == "[object Object]" )tree(obj[key],index+key+suffix+".");   
   }
 })(obj,"");
 return root;
}

अब, जटिल वस्तु को चपटा किया जा सकता है

var obj = previous definition;
var flat = flatten(obj);
var moe = flat["arr[0].name"];//moe

यहाँ jsFiddle Demoइस दृष्टिकोण का उपयोग किया जा रहा है।


क्या आप obj["arr[0].name"]इसके बजाय उपयोग करना चाहते हैं obj.arr[0].name? क्रमिकता को छोड़कर आपको चपटी वस्तुओं से निपटने की आवश्यकता है ।
बेर्गी

@ बर्गी - मैं इस सवाल को आमतौर पर देखता हूं, और चूंकि यह कैनोनिक रूप से उपयोग किया जा रहा है, इसलिए मैंने इसके संस्करण का उत्तर पोस्ट किया है। यदि यह टालने योग्य है तो obj.arr [0] .name का उपयोग करना अधिक तेज़ है, लेकिन कभी-कभी लोग स्ट्रिंग एक्सेसर्स को पास करना चाहते हैं और यह ऐसा करने का एक उदाहरण है।
ट्रैविस जे

Urgh। फिर भी, केवल एक स्ट्रिंग पथ का उपयोग करने के लिए पूरी वस्तु को समतल करने का शायद ही कोई कारण है, आप बस इसे पार्स कर सकते हैं और एक गतिशील खोज कर सकते हैं।
बेर्गी

14

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

const data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};

const {
  items: [, {
    name: secondName
  }]
} = data;

console.log(secondName);

ऊपर के उदाहरण एक चर बुलाया बनाता secondNameसे nameएक सरणी कहा जाता है से कुंजी items, अकेला ,सरणी में पहली वस्तु को छोड़ कहते हैं।

विशेष रूप से इस उदाहरण के लिए संभवतः ओवरकिल है, क्योंकि साधारण सरणी लहजे को पढ़ना आसान है, लेकिन सामान्य रूप से अलग वस्तुओं को तोड़ते समय यह उपयोगी होता है।

यह आपके विशिष्ट उपयोग के मामले में बहुत संक्षिप्त परिचय है, विनाशकारी एक असामान्य वाक्यविन्यास हो सकता है जो पहले इस्तेमाल किया जा सके। मैं अधिक जानने के लिए मोज़िला के विनाशकारी असाइनमेंट प्रलेखन को पढ़ने की सलाह दूंगा


13

नेस्टेड विशेषता तक पहुंचने के लिए, आपको उसका नाम निर्दिष्ट करना होगा और फिर ऑब्जेक्ट के माध्यम से खोजना होगा।

यदि आप पहले से ही सटीक रास्ता जानते हैं, तो आप इसे अपनी स्क्रिप्ट में हार्डकोड कर सकते हैं:

data['items'][1]['name']

ये भी काम करते हैं -

data.items[1].name
data['items'][1].name
data.items[1]['name']

जब आप हाथ से पहले सटीक नाम नहीं जानते हैं, या एक उपयोगकर्ता वह है जो आपके लिए नाम प्रदान करता है। फिर गतिशील रूप से डेटा संरचना के माध्यम से खोज करना आवश्यक है। कुछ यहाँ सुझाव दिया है कि खोज एक उपयोग किया जा सकता forपाश, लेकिन वहाँ का उपयोग कर एक रास्ता पार करने के लिए एक बहुत ही सरल तरीका है Array.reduce

const data = { code: 42, items: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }] }
const path = [ 'items', '1', 'name']
let result = path.reduce((a,v) => a[v], data)

पथ कहने का एक तरीका है: पहले उस वस्तु को कुंजी के साथ लें items, जो कि एक सरणी होती है। फिर 1-st तत्व (0 इंडेक्स एरेज़) लें। अंतिम ऑब्जेक्ट को nameउस एरे तत्व में कुंजी के साथ लें , जो स्ट्रिंग होता है bar

यदि आपके पास बहुत लंबा रास्ता है, तो आप String.splitइस सब को आसान बनाने के लिए भी उपयोग कर सकते हैं -

'items.1.name'.split('.').reduce((a,v) => a[v], data)

यह सिर्फ सादे जावास्क्रिप्ट है, बिना किसी तीसरे पक्ष के पुस्तकालयों जैसे कि jQuery या लॉश का उपयोग किए बिना।


13
var ourStorage = {


"desk":    {
    "drawer": "stapler"
  },
"cabinet": {
    "top drawer": { 
      "folder1": "a file",
      "folder2": "secrets"
    },
    "bottom drawer": "soda"
  }
};
ourStorage.cabinet["top drawer"].folder2; // Outputs -> "secrets"

या

//parent.subParent.subsubParent["almost there"]["final property"]

मूल रूप से, प्रत्येक वंश के बीच एक डॉट का उपयोग करें जो उसके नीचे प्रकट होता है और जब आपके पास दो तारों से बने ऑब्जेक्ट नाम होते हैं, तो आपको ["obj नाम"] नोटेशन का उपयोग करना होगा। अन्यथा, बस एक डॉट पर्याप्त होगा;

स्रोत: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-objects

इसे जोड़ने के लिए, नेस्टेड एरेज़ एक्सेस करना ऐसा होगा:

var ourPets = [
  {
    animalType: "cat",
    names: [
      "Meowzer",
      "Fluffy",
      "Kit-Cat"
    ]
  },
  {
    animalType: "dog",
    names: [
      "Spot",
      "Bowser",
      "Frankie"
    ]
  }
];
ourPets[0].names[1]; // Outputs "Fluffy"
ourPets[1].names[0]; // Outputs "Spot"

स्रोत: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays/

उपरोक्त स्थिति को दर्शाने वाला एक और उपयोगी दस्तावेज: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics#Bracket_notation

डॉट वॉकिंग के माध्यम से संपत्ति का उपयोग: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation


हालांकि यह लिंक प्रश्न का उत्तर दे सकता है, लेकिन उत्तर के आवश्यक भागों को शामिल करना और संदर्भ के लिए लिंक प्रदान करना बेहतर है। लिंक-केवल उत्तर अमान्य हो सकते हैं यदि लिंक किए गए पृष्ठ बदल जाते हैं। - समीक्षा से
रॉबर्ट

1
मैंने पोस्ट को एडिट किया। हालाँकि, लोगों को इस पर बुरा असर डालने की जल्दी थी। अगली बार जवाब देने से बचूंगा।
जॉनी

1
@ रिडीक मना न करें, बस यह सुनिश्चित करें कि आप केवल एक लिंक पोस्ट नहीं करते हैं
reggaeguitar

12

आप lodash _getफ़ंक्शन का उपयोग कर सकते हैं :

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.get(object, 'a[0].b.c');
// => 3

9

अगर आप लाइब्रेरी शामिल करने के इच्छुक हैं तो JSONPath का उपयोग करना सबसे अधिक लचीले समाधानों में से एक होगा: https://github.com/s3u/JSONPath (नोड और ब्राउज़र)

आपके उपयोग के मामले में json पथ होगा:

$..items[1].name

इसलिए:

var secondName = jsonPath.eval(data, "$..items[1].name");

1
Eval () का उपयोग करना अच्छा उपाय नहीं है। इसके बजाय प्रथम श्रेणी फ़ंक्शन का उपयोग किया जा सकता है।
प्रदीप गौड़ा

8

बस मामले में, किसी को भी 2017 में या बाद में इस सवाल का दौरा करने और एक आसान तरीका याद रखने के लिए, यहाँ जावास्क्रिप्ट में Nested ऑब्जेक्ट्स को बिना बाँधे जा रहे हैं

अपरिभाषित त्रुटि की संपत्ति 'फू' नहीं पढ़ सकते हैं

1. ओलिवर स्टील की नेस्टेड ऑब्जेक्ट एक्सेस पैटर्न

सबसे आसान और साफ तरीका ओलिवर स्टील की नेस्टेड ऑब्जेक्ट एक्सेस पैटर्न का उपयोग करना है

const name = ((user || {}).personalInfo || {}).name;

इस अंकन के साथ, आप कभी नहीं चलेंगे

अपरिभाषित की संपत्ति 'नाम' नहीं पढ़ सकते हैं

आप मूल रूप से जांचते हैं कि उपयोगकर्ता मौजूद है, यदि नहीं, तो आप मक्खी पर एक खाली वस्तु बनाते हैं। इस तरह, अगली स्तर की कुंजी हमेशा उस ऑब्जेक्ट से एक्सेस की जाएगी जो मौजूद है या एक खाली ऑब्जेक्ट है , लेकिन अपरिभाषित से कभी नहीं।

2. ऐरे रिड्यूस का उपयोग करके नेस्टेड ऑब्जेक्ट्स तक पहुंचें

नेस्टेड सरणियों का उपयोग करने में सक्षम होने के लिए, आप अपनी सरणी कम उपयोग लिख सकते हैं।

const getNestedObject = (nestedObj, pathArr) => {
    return pathArr.reduce((obj, key) =>
        (obj && obj[key] !== 'undefined') ? obj[key] : undefined, nestedObj);
}

// pass in your object structure as array elements
const name = getNestedObject(user, ['personalInfo', 'name']);

// to access nested array, just pass in array index as an element the path array.
const city = getNestedObject(user, ['personalInfo', 'addresses', 0, 'city']);
// this will return the city from the first address item.

वहाँ भी एक उत्कृष्ट प्रकार कम से कम पुस्तकालय से निपटने है typy है कि आप के लिए यह सब करता है।


3
यह प्रश्न मुख्य रूप से मौजूद गुणों के बारे में है। पहले से ही एक सवाल है कि आप किस चीज का उल्लेख कर रहे हैं (और पहले से ही आपके अधिकांश समाधानों सहित): जावास्क्रिप्ट को नेस्टेड ऑब्जेक्ट्स को सुरक्षित रूप से एक्सेस करें या स्ट्रिंग नेस्ट के साथ नेस्टेड जावास्क्रिप्ट ऑब्जेक्ट्स एक्सेस करें । लेकिन वैसे भी: "दुर्भाग्य से, आप नेस्टेड सरणियों इस चाल के साथ उपयोग नहीं कर सकते।" क्यों नहीं? Arrays ऑब्जेक्ट हैं, इसलिए इसे बस काम करना चाहिए। क्या आप एक उदाहरण प्रदान कर सकते हैं जहां यह नहीं है?
फेलिक्स क्लिंग

1
@FelixKling जब हम ओलिवर स्टील पैटर्न के साथ सरणियों का उपयोग करने का प्रयास करते हैं, तो हम 'अपरिभाषित' त्रुटि प्राप्त किए बिना मक्खी पर 'एन' की लंबाई और एनटीटी सूचकांक तक पहुंच बनाने में सक्षम नहीं होंगे। पूर्व। ((user || {}).address || new Array(3))[1].name
दिनेश पांडियन

3
आप अपने पैटर्न को लगातार लागू नहीं कर रहे हैं। ...[1].barयदि तत्व 1मौजूद नहीं था , तो निश्चित रूप से एक त्रुटि होगी । लेकिन ....foo.barअगर fooऐसा नहीं होता तो भी यही होता। आपको "गार्ड" तक पहुंच प्राप्त करनी होगी 1, ठीक वैसे ही जैसे आप किसी अन्य संपत्ति के एक्सेस पर "गार्ड" करते हैं। एक सरणी सिर्फ एक वस्तु है। एक "सरणी तत्व" सिर्फ एक संपत्ति है। सही ढंग से लागू किया जाएगा (((user || {}).address || {})[1] || {}).name
फेलिक्स क्लिंग

1
यह भी खूब रही। इसने मुझे इस तरह नहीं मारा। @FelixKling को धन्यवाद, मैं ब्लॉग पोस्ट को अपडेट करूंगा।
दिनेश पांडियन

2
@ दिनेश पांडियान आपको खुलासा करना चाहिए कि आप टाइप के लेखक हैं, मैं आपके ब्लॉग पोस्ट को पढ़ने के बाद यहाँ आया था
reggaeguitar


7

गतिशील रूप से मल्टी लेवल ऑब्जेक्ट तक पहुँचना।

var obj = {
  name: "john doe",
  subobj: {
    subsubobj: {
      names: "I am sub sub obj"
    }
  }
};

var level = "subobj.subsubobj.names";
level = level.split(".");

var currentObjState = obj;

for (var i = 0; i < level.length; i++) {
  currentObjState = currentObjState[level[i]];
}

console.log(currentObjState);

कार्य बेला: https://jsfiddle.net/andreitodorut/3mws3kjL/


6

यदि आप एक या एक से अधिक वस्तुओं की तलाश कर रहे हैं जो कुछ मानदंडों को पूरा करती हैं तो आपके पास क्वेरी-जेएस का उपयोग करने वाले कुछ विकल्प हैं

//will return all elements with an id larger than 1
data.items.where(function(e){return e.id > 1;});
//will return the first element with an id larger than 1
data.items.first(function(e){return e.id > 1;});
//will return the first element with an id larger than 1 
//or the second argument if non are found
data.items.first(function(e){return e.id > 1;},{id:-1,name:""});

वहाँ भी है singleऔर singleOrDefaultवे क्रमशः firstऔर अधिक की तरह काम करते firstOrDefaultहैं। फर्क सिर्फ इतना है कि एक से अधिक मैच पाए जाने पर वे फेंक देंगे ।

क्वेरी-जे के और स्पष्टीकरण के लिए आप इस पोस्ट से शुरुआत कर सकते हैं


मुझे यह जानना अच्छा लगेगा कि इसमें सुधार कैसे किया जा सकता है। एक टिप्पणी छोड़ने का ध्यान रखें?
FS

6

अंडरस्कोर जेएस वे

जो एक जावास्क्रिप्ट लाइब्रेरी है functional programmingजो किसी भी निर्मित वस्तुओं को विस्तारित किए बिना उपयोगी सहायकों की एक पूरी गड़बड़ी प्रदान करता है ।

समाधान:

var data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};

var item = _.findWhere(data.items, {
  id: 2
});
if (!_.isUndefined(item)) {
  console.log('NAME =>', item.name);
}

//using find - 

var item = _.find(data.items, function(item) {
  return item.id === 2;
});

if (!_.isUndefined(item)) {
  console.log('NAME =>', item.name);
}

6

पुराना सवाल है, लेकिन किसी ने भी दर्ज नहीं किया है (सिर्फ अंडरस्कोर)।

यदि आप पहले से ही अपनी परियोजना में लॉश का उपयोग कर रहे हैं, तो मुझे लगता है कि यह एक जटिल उदाहरण में एक सुंदर तरीका है:

ऑप्ट १

_.get(response, ['output', 'fund', 'data', '0', 'children', '0', 'group', 'myValue'], '')

के समान:

ऑप्ट २

response.output.fund.data[0].children[0].group.myValue

पहले और दूसरे विकल्प के बीच का अंतर यह है कि ऑप्ट 1 में यदि आपके पास उस पथ में अनुपलब्ध (अपरिभाषित) है जिसमें आपको कोई त्रुटि नहीं मिलती है, तो यह आपको तीसरा पैरामीटर देता है।

सरणी फ़िल्टर के लिए लॉश है, _.find()लेकिन मैं नियमित रूप से उपयोग करना चाहता हूँ filter()। लेकिन मुझे अभी भी लगता है कि _.get()वास्तव में जटिल डेटा के साथ काम करते समय उपरोक्त विधि सुपर उपयोगी है। मैं वास्तव में जटिल एपीआई का सामना कर रहा था और यह आसान था!

मुझे उम्मीद है कि यह उन लोगों के लिए उपयोगी हो सकता है जो वास्तव में जटिल डेटा को हेरफेर करने के लिए विकल्पों की तलाश कर रहे हैं जो शीर्षक का अर्थ है।


5

मुझे नहीं लगता कि प्रश्नकर्ता सिर्फ एक स्तर के नेस्टेड ऑब्जेक्ट की चिंता करता है, इसलिए मैं निम्नलिखित डेमो को प्रदर्शित करता हूं कि कैसे गहन नेस्टेड ऑब्जेक्ट के नोड का उपयोग किया जाए। सब ठीक है, आइए आईडी '5' के साथ नोड ढूंढें।

var data = {
  code: 42,
  items: [{
    id: 1,
    name: 'aaa',
    items: [{
        id: 3,
        name: 'ccc'
      }, {
        id: 4,
        name: 'ddd'
      }]
    }, {
    id: 2,
    name: 'bbb',
    items: [{
        id: 5,
        name: 'eee'
      }, {
        id: 6,
        name: 'fff'
      }]
    }]
};

var jsonloop = new JSONLoop(data, 'id', 'items');

jsonloop.findNodeById(data, 5, function(err, node) {
  if (err) {
    document.write(err);
  } else {
    document.write(JSON.stringify(node, null, 2));
  }
});
<script src="https://rawgit.com/dabeng/JSON-Loop/master/JSONLoop.js"></script>


मैं चर का उपयोग करके नेस्टेड जोंस ऑब्जेक्ट का उपयोग कैसे कर सकता हूं। data = {a: {b: 'ss'}}; var key = ab data [key] काम नहीं कर रहा है
Pasupathi Rajamanickam

3

आप jsonObject.keyमान तक पहुंचने के लिए सिंटैक्स का उपयोग कर सकते हैं । और यदि आप किसी ऐरे से मान चाहते हैं, तो आप सिंटैक्स का उपयोग कर सकते हैं jsonObjectArray[index].key

यहां आपको विचार देने के लिए विभिन्न मूल्यों तक पहुंचने के लिए कोड उदाहरण दिए गए हैं।

        var data = {
            code: 42,
            items: [{
                id: 1,
                name: 'foo'
            }, {
                id: 2,
                name: 'bar'
            }]
        };

        // if you want 'bar'
        console.log(data.items[1].name);

        // if you want array of item names
        console.log(data.items.map(x => x.name));

        // get the id of the item where name = 'bar'
        console.log(data.items.filter(x => (x.name == "bar") ? x.id : null)[0].id);


3

गतिशील दृष्टिकोण

नीचे deep(data,key)फ़ंक्शन में, आप मनमाने ढंग से keyस्ट्रिंग का उपयोग कर सकते हैं - आपके मामले में items[1].name(आप [i]किसी भी स्तर पर सरणी संकेतन का उपयोग कर सकते हैं ) - यदि कुंजी अमान्य है तो अपरिभाषित वापसी है।


2

JSON पेड़ों को अनियंत्रित करने के लिए एक पायथोनिक, पुनरावर्ती और कार्यात्मक दृष्टिकोण:

handlers = {
    list:  iterate,
    dict:  delve,
    str:   emit_li,
    float: emit_li,
}

def emit_li(stuff, strong=False):
    emission = '<li><strong>%s</strong></li>' if strong else '<li>%s</li>'
    print(emission % stuff)

def iterate(a_list):
    print('<ul>')
    map(unravel, a_list)
    print('</ul>')

def delve(a_dict):
    print('<ul>')
    for key, value in a_dict.items():
        emit_li(key, strong=True)
        unravel(value)
    print('</ul>')

def unravel(structure):
    h = handlers[type(structure)]
    return h(structure)

unravel(data)

जहां डेटा एक पायथन सूची है (JSON टेक्स्ट स्ट्रिंग से पार्स किया गया है):

data = [
    {'data': {'customKey1': 'customValue1',
           'customKey2': {'customSubKey1': {'customSubSubKey1': 'keyvalue'}}},
  'geometry': {'location': {'lat': 37.3860517, 'lng': -122.0838511},
               'viewport': {'northeast': {'lat': 37.4508789,
                                          'lng': -122.0446721},
                            'southwest': {'lat': 37.3567599,
                                          'lng': -122.1178619}}},
  'name': 'Mountain View',
  'scope': 'GOOGLE',
  'types': ['locality', 'political']}
]

6
यह सवाल जावास्क्रिप्ट के बारे में है, पाइथन के बारे में नहीं। निश्चित नहीं है कि पाइथन के लिए कोई समकक्ष प्रश्न है या नहीं।
फेलिक्स क्लिंग

2

jQuery का grep फ़ंक्शन आपको एक सरणी के माध्यम से फ़िल्टर करने देता है:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

$.grep(data.items, function(item) {
    if (item.id === 2) {
        console.log(item.id); //console id of item
        console.log(item.name); //console name of item
        console.log(item); //console item object
        return item; //returns item object
    }

});
// Object {id: 2, name: "bar"}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


2
// const path = 'info.value[0].item'
// const obj = { info: { value: [ { item: 'it works!' } ], randominfo: 3 }  }
// getValue(path, obj)

export const getValue = ( path , obj) => {
  const newPath = path.replace(/\]/g, "")
  const arrayPath = newPath.split(/[\[\.]+/) || newPath;

  const final = arrayPath.reduce( (obj, k) => obj ?  obj[k] : obj, obj)
  return final;
}

2

2020 में, आप @ babel / प्लगइन-प्रस्ताव-वैकल्पिक-चेनिंग का उपयोग कर सकते हैं यह एक ऑब्जेक्ट में नेस्टेड मान तक पहुंचने के लिए बहुत आसान है।

 const obj = {
 foo: {
   bar: {
     baz: class {
   },
  },
 },
};

const baz = new obj?.foo?.bar?.baz(); // baz instance

const safe = new obj?.qux?.baz(); // undefined
const safe2 = new obj?.foo.bar.qux?.(); // undefined

https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining

https://github.com/tc39/proposal-optional-chaining


-4

मेरा stringdataPHP फ़ाइल से आ रहा है, लेकिन फिर भी, मैं यहाँ इंगित करता हूँ var। जब मैं सीधे अपने json में ले जाता हूँ objतो यह कुछ भी नहीं दिखाएगा कि मैं अपनी json फाइल को क्यों डालूँ

var obj=JSON.parse(stringdata); इसलिए उसके बाद मुझे messageओब्जेस्ट मिलता है और अलर्ट बॉक्स में दिखाता हूं, फिर मुझे dataजो जोसन एरे मिलता है और एक वेरिएबल में स्टोर होता है, ArrObjतो मैं उस एरे की पहली ऑब्जेक्ट को इस तरह से महत्वपूर्ण मान के साथ पढ़ता हूंArrObj[0].id

     var stringdata={
        "success": true,
        "message": "working",
        "data": [{
                  "id": 1,
                  "name": "foo"
         }]
      };

                var obj=JSON.parse(stringdata);
                var key = "message";
                alert(obj[key]);
                var keyobj = "data";
                var ArrObj =obj[keyobj];

                alert(ArrObj[0].id);

2
उदाहरण भ्रामक है क्योंकि stringjsonकोई स्ट्रिंग नहीं है।
फेलिक्स क्लिंग

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