ネストされたオブジェクト、配列、JSONにアクセスして処理するにはどうすればよいですか?


875

オブジェクトと配列を含むネストされたデータ構造があります。どのようにして情報を抽出できますか、つまり特定または複数の値(またはキー)にアクセスできますか?

例えば:

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

name2番目の項目のにアクセスするにはどうすればよいitemsですか?


22
@Marcel:「データのネストされたデータ構造または JSONがあります。どのようにして特定の値にアクセスできますか?」と読む必要があります。は違い知っていますが、多くの人はそうではなく、「オブジェクト」ではなく「JSON」を検索している可能性があります。多くの質問は、実際には「このJSONでXにアクセスするにはどうすればよいですか」という形式です。私の回答でJSONについて言及する唯一の場所は、それが何であるかを説明するところです。これをより良い方法で伝える方法についての提案があれば、私はすべて耳にします。
Felix Kling 2013年

回答:


1160

予選

JavaScriptには、複数の値を含むことができる1つのデータ型のみがあります:Objectアレイは、オブジェクトの特殊な形態です。

(プレーン)オブジェクトの形式は

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

配列の形式は

[value, value, ...]

配列とオブジェクトの両方がkey -> value構造を公開します。配列のキーは数値である必要がありますが、オブジェクトのキーとして任意の文字列を使用できます。キーと値のペアは「プロパティ」とも呼ばれます

プロパティは、ドット表記を使用してアクセスできます

const value = obj.someProperty;

またはブラケット表記(プロパティ名が有効なJavaScript 識別子名[spec]ではない場合、または名前が変数の値である場合):

// 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などと同様に、データのテキスト表現です。このようなデータを操作するには、まず配列とオブジェクトなどのJavaScriptデータ型に変換する必要があります(これらの操作方法については先ほど説明しました)。JSONを解析する方法は、JavaScriptでのJSONの解析の質問で説明されていますか?

さらに読む資料

配列とオブジェクトにアクセスする方法は、JavaScriptの基本的な知識であるため、MDN JavaScriptガイド、特にセクションを読むことをお勧めします



ネストされたデータ構造へのアクセス

ネストされたデータ構造は、他の配列またはオブジェクトを参照する配列またはオブジェクトです。つまり、その値は配列またはオブジェクトです。このような構造には、ドットまたはブラケット表記を連続して適用することによってアクセスできます。

次に例を示します。

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

name2番目の項目のにアクセスしたいとします。

手順を追って説明します。

ご覧のとおりdata、オブジェクトなので、ドット表記を使用してそのプロパティにアクセスできます。items次のようにプロパティがアクセスされます:

data.items

値は配列です。2番目の要素にアクセスするには、ブラケット表記を使用する必要があります。

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 [MDN]でこれを行うことができます。

for...inwithの代わりに、[MDN]hasOwnProperty使用してプロパティ名の配列を取得できますObject.keys

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

配列

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配列を反復処理するために使用することもできますが、これを回避する必要がある理由があります。JavaScriptでの配列の「for(var item in list)」が悪い習慣と見なされるのはなぜですか?

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で、イテラブルの次の要素を直接提供します。アクセスまたは使用する「インデックス」はありません。


データ構造の「深さ」が不明な場合はどうなりますか?

不明なキーに加えて、データ構造の「深さ」(つまり、ネストされたオブジェクトの数)も不明である可能性があります。深くネストされたプロパティにアクセスする方法は、通常、正確なデータ構造によって異なります。

しかし、データ構造に繰り返しパターン(バイナリツリーの表現など)が含まれている場合、ソリューションには通常、データ構造の各レベルに再帰的に アクセスする[Wikipedia]ことが含まれます。

バイナリツリーの最初のリーフノードを取得する例を次に示します。

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 [MDN]console.dir [MDN]はこれを行うのに役立ちます。例(Chromeコンソールの出力):

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

ここでdata.itemsは、それが両方ともオブジェクトである2つの要素を持つ配列であることがわかります。Chromeコンソールでは、オブジェクトをすぐに展開して検査することもできます。

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

これdata.items[1]は、それがオブジェクトであることを示しておりid、展開するnameと、3つのプロパティ、およびがあることがわかり__proto__ます。後者は、オブジェクトのプロトタイプチェーンに使用される内部プロパティです。ただし、プロトタイプチェーンと継承はこの回答の範囲外です。


3
ここでリンクされているもののいくつかは、jQueryでこれを実行する方法を実際に尋ねています。これをメガポストにするか、個別に回答するかは不明です。オブジェクトとは何か、配列とは何かについての基本は、通常、実際に要求されるものです。
Chris Moschini、2013

1
@ felix-kling 1つのこと...などのネストされたオブジェクトでlet object = {a: 1, b: 2, c: { a: 3, b: 4 }};は、ネストされた各オブジェクトの配列を含む配列が返されます。この場合[ 1, 2, [ 3, 4 ] ]は、pushの代わりに再帰呼び出しでconcatを使用する方が良いでしょうか?(結果を変更可能にする必要があります)
ElFitz

3
これは、Stack Overflowでこれまでに見た中で最も詳細な答えです。ありがとう!
ウィリアムジョーンズ

この1ページでは、私はARRAYとOBJとの違いを学ぶなさ
4ni5

76

この方法でアクセスできます

data.items[1].name

または

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

どちらの方法も同じです。


でも、data ["items"]。1.nameを実行することはできません
neaumusic

5
最初ははるかに直感的で読みやすく、短いです;)プロパティ名が変数である場合にのみ、ブラケットプロパティ構文を使用することを好みます。
DanteTheSmith 2017年

35

またはでitem構造体の例にアクセスしようとしている場合、配列内の位置を知らなくても、最も簡単な方法は、underscore.jsライブラリを使用することです。idname

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

私の経験では、foror 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() for-ofループとdestructuring割り当て

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

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

これは、結果反復するために非常に便利だObject.entries()ループの-用および分割代入を

for-ofループを使用すると、配列要素を反復できます。構文は次のとおりですfor (const element of array)(私たちは置き換えることができconstvarlet、それは使用することをお勧めしますconst、我々は変更する予定がない場合element)。

構造化代入では、配列またはオブジェクトから値を抽出し、それらを変数に代入できます。この場合const [key, value][key, value]配列をに割り当てる代わりに、その配列elementの最初の要素をに割り当てkey、2番目の要素をに割り当てvalueます。これは次と同等です。

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

ご覧のように、構造化を解除すると、これがはるかに簡単になります。

Array.prototype.every() そして Array.prototype.some()

このevery()メソッドはtrue、指定されたコールバック関数が配列のすべての要素trueに対して戻る場合に戻ります。このメソッドは、指定されたコールバック関数が一部(少なくとも1つ)の要素に対して戻る場合に戻ります。some()truetrue

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()メソッドは、提供されたコールバック関数を2つの要素で呼び出すことにより、配列を単一の値に減らします。

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()メソッドは、オプションの2番目のパラメーター(初期値)を取ります。これは、呼び出す配列のreduce()要素が0または1の場合に役立ちます。たとえば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


これが私のお気に入りの答えです。また同様に、ループのためだけexpecificネストされたデータを例を追加することができます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内の値を見つけるためのアプローチも複雑になります。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これは、使用されているこのアプローチの1つです。


WTHのobj["arr[0].name"]代わりに使用しobj.arr[0].nameますか?シリアライゼーションを除いて、フラット化されたオブジェクトを処理する必要はほとんどありません。
Bergi 14

@Bergi-私はこの質問をよく見ます。これは標準的に使用されているため、そのバージョンの回答を投稿しました。回避できる場合はobj.arr [0] .nameを使用する方がはるかに高速ですが、文字列アクセサーを渡したい場合もあり、これはその例です。
Travis J

ああ。それでも、単一の文字列パスを使用するためだけに完全なオブジェクトをフラット化する理由はほとんどありません。単純にそれを解析して動的ルックアップを実行できます。
ベルギ2014

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、孤独は、,配列内の最初のオブジェクトをスキップ言います。

特に、単純な配列アクセスの方が読みやすいので、この例ではおそらくやり過ぎですが、一般的にオブジェクトを分解するときに役立ちます。

これは特定のユースケースのごく簡単な紹介です。構造化は、最初は慣れ親しんだ珍しい構文になる可能性があります。詳細についてはMozillaのDestructuring Assignmentのドキュメントを読むことをお勧めします。


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に、配列であるkey でオブジェクトを取得します。次に、1-st要素(0インデックス配列)を取ります。最後に、name配列要素のキーを持つオブジェクトを取得しますbar。これはたまたまstring です。

パスが非常に長い場合は、これを使用String.splitしてすべてを簡単にすることもできます-

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

これは単なるjQueryであり、jQueryやlodashなどのサードパーティのライブラリを使用していません。


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

基本的に、各子孫の間には、その下に展開するドットを使用します。2つの文字列からオブジェクト名を作成する場合は、["obj Name"]表記を使用する必要があります。それ以外の場合は、ドットのみで十分です。

ソース: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
@Riddickは控えず、リンクのみを投稿しないようにしてください
reggaeguitar

12

あなたはlodash _get関数を使うことができます:

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

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

9

ライブラリを含める場合は、JSONPathを使用することが最も柔軟なソリューションの1つになります。https//github.com/s3u/JSONPath(ノードとブラウザー)

ユースケースの場合、jsonパスは次のようになります。

$..items[1].name

そう:

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

1
eval()の使用は良い解決策ではありません。代わりに、ファーストクラス関数を使用できます。
プラディープゴウダ2017

8

念のため、誰のは、2017年以降にこの質問を訪問し、探しやすく、覚えている方法は、ここに精巧なブログの投稿のアクセスネストされたが、JavaScriptでオブジェクトによって酔っぱらっされることなく、

未定義エラーのプロパティ 'foo'を読み取れません

1. Oliver Steeleのネストされたオブジェクトアクセスパターン

最も簡単でクリーンな方法は、Oliver Steeleのネストされたオブジェクトアクセスパターンを使用することです。

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

この表記では、決して遭遇することはありません

undefinedのプロパティ 'name'を読み取れません

基本的に、ユーザーが存在するかどうかを確認し、存在しない場合は、その場で空のオブジェクトを作成します。このようにして、次のレベルのキーは常に、存在するオブジェクトまたは空のオブジェクトからアクセスされますが、未定義からアクセスされることはありません。

2. Array Reduceを使用してネストされたオブジェクトにアクセスする

ネストされた配列にアクセスできるようにするには、独自の配列reduce utilを作成できます。

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
この質問は、主に存在するアクセスプロパティについてです。あなたが何を参照しているのか(そしてほとんどのソリューションをすでに含んでいる)についての質問はすでにあります:Javascriptのネストされたオブジェクトに安全にアクセスする、文字列キーでネストされたJavaScriptオブジェクトにアクセスします。しかし、とにかく:「残念ながら、このトリックではネストされた配列にアクセスできません。」何故なの?配列はオブジェクトなので、同様に機能するはずです。それができない例を提供できますか?
Felix Kling 2018

1
@FelixKling Oliver Steeleパターンで配列にアクセスしようとすると、オンザフライで「n」の長さの配列を作成し、「undefined」エラーなしでn番目のインデックスにアクセスできません。例 ((user || {}).address || new Array(3))[1].name
Dinesh Pandiyan

3
パターンを一貫して適用していません。もちろん...[1].bar、要素1が存在しない場合はエラーになります。しかし、それはまたのためのケースだ....foo.bar場合はfoo存在しませんでした。1他のプロパティへのアクセスを「ガード」するのと同じように、アクセスも「ガード」する必要があります。配列は単なるオブジェクトです。「配列要素」は単なるプロパティです。正しく適用されます(((user || {}).address || {})[1] || {}).name
Felix Kling 2018

1
これは素晴らしい。このように私を襲ったわけではありません。@FelixKlingに感謝します。ブログの投稿を更新します。
Dinesh Pandiyan

2
@DineshPandiyanは、あなたがtypyの作者であることを開示するべきです。私はあなたのブログ投稿を読んだ後、ここに来ました
reggaeguitar

8

私はjQueryを好みます。見やすく、読みやすくなっています。

$.each($.parseJSON(data), function (key, value) {
  alert(value.<propertyname>);
});

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

特定の条件を満たす1つ以上のオブジェクトを探している場合は、query-jsを使用するいくつかのオプションがあります

//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:""});

a singleとa もあり、それぞれとsingleOrDefault同様に機能firstfirstOrDefaultます。唯一の違いは、複数の一致が見つかった場合にスローすることです。

query-jsの詳細については、この投稿から始めることができます


これをどのように改善できるか知りたいです。コメントを残しますか?
ルーンFS

6

アンダースコアjsウェイ

これは、functional programming組み込みオブジェクトを拡張することなく、便利なヘルパー全体を提供するJavaScriptライブラリです。

解決:

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

古い質問ですが、誰もlodashに言及していません(ちょうどアンダースコア)。

プロジェクトですでにlodashを使用している場合、複雑な例でこれを行うにはエレガントな方法だと思います。

オプション1

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

と同じ:

オプション2

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

1番目と2番目のオプションの違いは、オプション1では、パスにプロパティの1つが欠落している(未定義の)場合、エラーが発生せず、3番目のパラメーターが返されることです。

配列フィルターの場合、lodashにはあります_.find()が、通常のを使用しfilter()ます。しかし、私はまだ上記の方法_.get()が本当に複雑なデータを扱うときに非常に役立つと思います。私は過去に本当に複雑なAPIに直面し、それは便利でした!

タイトルが意味する本当に複雑なデータを操作するためのオプションを探している人に役立つことを願っています。


5

質問者は1レベルのネストされたオブジェクトだけに関係しているとは思わないので、深くネストされたjsonオブジェクトのノードにアクセスする方法を示す次のデモを紹介します。では、IDが「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>


変数を使用してネストされたjsonオブジェクトにアクセスするにはどうすればよいですか。データ= {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]任意のレベルで配列表記を使用できます)-キーが無効な場合、undefinedが返されます。


2

任意のJSONツリーを解明するためのpythonicの再帰的で機能的なアプローチ:

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)

ここで、dataはPythonリストです(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
この質問は、PythonではなくJavaScriptに関するものです。Pythonに同等の質問があるかどうかはわかりません。
Felix Kling 2016

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 / plugin-proposal-optional-chainingを使用して、オブジェクト内のネストされた値に非常に簡単にアクセスできます。

 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

stringdataはPHPファイルから来ていますが、それでも私はここで示していますvar。私がjsonを直接objそこに取り込むと、何も表示されないので、jsonファイルを

var obj=JSON.parse(stringdata); その後、私はmessageobjを取得してアラートボックスに表示し、次にdatajson配列である1つを取得して1つの変数に格納し、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は文字列ではないため、例はわかりにくいです。
Felix Kling

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.