Как я могу получить доступ и обработать вложенные объекты, массивы или JSON?

У меня есть вложенная структура данных, содержащая объекты и массивы. Как я могу извлечь информацию, т.е. Получить доступ к определенным или нескольким значениям (или ключам)?

Например:

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

Как я могу получить доступ к name второго элемента в items?

+770
12 авг. '12 в 13:02
источник поделиться
22 ответа

Отборочные

JavaScript имеет только один тип данных, который может содержать несколько значений: Объект. Массив - это особая форма объекта.

(Plain) Объекты имеют вид

{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 объясняется в вопросе Parse JSON в JavaScript?.

Дополнительный материал для чтения

Как получить доступ к массивам и объектам является фундаментальным знанием JavaScript, и поэтому рекомендуется прочитать Руководство по JavaScript MDN, особенно разделы



Доступ к вложенным структурам данных

Вложенная структура данных представляет собой массив или объект, который относится к другим массивам или объектам, т.е. его значения представляют собой массивы или объекты. К таким структурам можно получить последовательное применение точечной или скобкой.

Вот пример:

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 [MDN].

В качестве альтернативы for...in с hasOwnProperty вы можете использовать Object.keys [MDN] для получить массив имен свойств:

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 для итерации по массивам, но есть причины, по которым этого следует избегать: Почему "для (элемент var в списке)" с массивами, считающимися плохими практика в JavaScript?.

При увеличении поддержки браузера 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), вы также можете использовать цикл for...of [MDN], который не только работает для массивов, но и для любого iterable:

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

В каждой итерации for...of непосредственно дает нам следующий элемент итерации, нет никакого "индекса" для доступа или использования.


Что делать, если "глубина" структуры данных мне неизвестна?

В дополнение к неизвестным ключам, "глубина" структуры данных (например, сколько вложенных объектов) она имеет, также может быть неизвестна. Как получить доступ к глубоко вложенным свойствам, как правило, зависит от точной структуры данных.

Но если структура данных содержит повторяющиеся шаблоны, например. представление двоичного дерева, решение обычно включает в себя рекурсивно [Wikipedia] доступ каждый уровень структуры данных.

Вот пример, чтобы получить первый лист node двоичного дерева:

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

const root = {
    leftChild: {
        leftChild: {
            leftChild: null,
            rightChild: null,
            data: 42
        },
        rightChild: {
            leftChild: null,
            rightChild: null,
            data: 5
        }
    },
    rightChild: {
        leftChild: {
            leftChild: null,
            rightChild: null,
            data: 6
        },
        rightChild: {
            leftChild: null,
            rightChild: null,
            data: 7
        }
    }
};
function getLeaf(node) {
    if (node.leftChild) {
        return getLeaf(node.leftChild);
    } else if (node.rightChild) {
        return getLeaf(node.rightChild);
    } else { // node must be a leaf node
        return node;
    }
}

console.log(getLeaf(root).data);

Более общий способ доступа к вложенной структуре данных с неизвестными ключами и глубиной - проверить тип значения и действовать соответствующим образом.

Вот пример, который добавляет все примитивные значения внутри вложенной структуры данных в массив (при условии, что он не содержит каких-либо функций). Если мы сталкиваемся с объектом (или массивом), мы просто вызываем 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;
}

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


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

console.log(toArray(data));


Помощники

Поскольку структура сложного объекта или массива не обязательно очевидна, мы можем проверить значение на каждом шаге, чтобы решить, как двигаться дальше. console.log [MDN] и console.dir [MDN] помогите нам в этом. Например (вывод консоли Chrome):

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

Здесь мы видим, что data.items представляет собой массив с двумя элементами, которые являются обоими объектами. В консоли Chrome объекты можно даже быстро развернуть и проверить.

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

Это говорит нам, что data.items[1] является объектом, и после его расширения мы видим, что он имеет три свойства: id, name и __proto__. Последний является внутренним свойством, используемым для прототипа цепочки объекта. Однако цепочка прототипов и наследование не подходят для этого ответа.

+1042
12 авг. '12 в 13:02
источник

Связанные вопросы


Похожие вопросы

Вы можете получить к нему доступ таким образом

data.items[1].name

или

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

Оба способа равны.

+67
14 мая '13 в 3:29
источник

Если вы пытаетесь получить доступ к 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 цента.

+32
29 июн. '13 в 9:15
источник

Иногда доступ к вложенному объекту с использованием строки может быть желательным. Простым подходом является первый уровень, например

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

Но это часто бывает не со сложным json. По мере усложнения json подходы к определению значений внутри json также становятся сложными. Рекурсивный подход для навигации по json лучше всего, и то, как эта рекурсия используется, будет зависеть от типа поиска данных. Если есть условные заявления, json search может быть хорошим инструментом для использования.

Если доступное свойство уже известно, но путь является сложным, например, в этом объекте

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.

+21
18 авг. '14 в 19:20
источник

Объекты и массивы имеют множество встроенных методов, которые могут помочь вам в обработке данных.

Примечание: во многих примерах я использую функции стрелок. Они аналогичны выражениям , но они привязывают значение 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-loop и 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 loop и назначение деструкции.

For-loop позволяет вам итерации элементов массива. Синтаксис 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 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
+17
22 окт. '16 в 18:38
источник

Этот вопрос довольно старый, так как современное обновление. С наступлением 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, чтобы узнать больше.

+11
06 мая '16 в 10:45
источник

Чтобы получить доступ к вложенному атрибуту, необходимо указать его имя, а затем выполнить поиск по объекту.

Если вы уже знаете точный путь, вы можете жестко закодировать его в своем скрипте следующим образом:

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)

Это просто обычный JavaScript, без использования сторонних библиотек, таких как jQuery или lodash.

+9
15 февр. '18 в 10:06
источник

Использование JSONPath будет одним из самых гибких решений, если вы хотите включить библиотеку: https://github.com/s3u/JSONPath (node и браузер)

Для вашего случая использования путь json:

$..items[1].name

так:

var secondName = jsonPath.eval(data, "$..items[1].name");
+8
26 июн. '14 в 12:43
источник

Вы можете использовать функцию lodash _get:

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

_.get(object, 'a[0].b.c');
// => 3
+7
02 июл. '17 в 19:08
источник

Я предпочитаю JQuery. Это чище и легко читается.

 $.each($.parseJSON(data), function (key, value) {
    alert(value.<propertyname>);
});
+7
24 февр. '16 в 15:55
источник
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 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

+6
19 авг. '18 в 23:01
источник

Старый вопрос, но как никто не упоминал lodash (просто подчеркивание).

Если вы уже используете lodash в своем проекте, я думаю, что это элегантный способ сделать это в сложном примере:

Opt 1

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

то же самое, что:

Opt 2

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

Разница между первой и второй опцией заключается в том, что в Оптим 1, если у вас есть одно из отсутствующих свойств (undefined), в пути вы не получите ошибку, он возвращает вы третий параметр.

Для фильтра массива lodash есть _.find(), но я бы предпочел использовать регулярный filter(). Но я все же считаю, что вышеприведенный метод _.get() очень полезен при работе с действительно сложными данными. В прошлом я столкнулся с действительно сложными API-интерфейсами, и это было удобно!

Я надеюсь, что это может быть полезно для тех, кто ищет варианты для обработки действительно сложных данных, которые подразумевает название.

+5
01 июл. '17 в 11:46
источник

Если вы ищете один или несколько объектов, которые соответствуют определенным критериям, у вас есть несколько вариантов, используя 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:""});

Есть также single и singleOrDefault они работают так же, как first и firstOrDefault соответственно. Разница лишь в том, что они будут бросать, если найдено более одного совпадения.

для дальнейшего объяснения query-js вы можете начать с этого поста

+5
17 июн. '15 в 12:16
источник

Подсвечник js Way

Что такое библиотека JavaScript, которая предоставляет целый беспорядок полезных помощников 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);
}
+5
13 авг. '16 в 10:39
источник

Доступ к динамически многоуровневому объекту.

var obj = {
  name: "salut",
  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/

+4
25 янв. '18 в 10:24
источник

Я не думаю, что вопросник касается только одного вложенного объекта уровня, поэтому я представляю следующую демонстрацию, чтобы продемонстрировать, как получить доступ к node глубоко вложенного объекта json. Хорошо, найдем node с 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>
+4
22 февр. '17 в 9:00
источник

На всякий случай, любой, кто посещает этот вопрос в 2017 году или позже и ищет легкий для запоминания способ, здесь выложено сообщение в блоге о доступе к вложенным объектам в JavaScript, не будучи обманутым

Невозможно прочитать свойство "foo" неопределенной ошибки

1. Схема доступа вложенных объектов Oliver Steele

Самый простой и чистый способ - использовать шаблон доступа вложенных объектов Oliver Steele

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

С этими обозначениями вы никогда не столкнетесь с

Невозможно прочитать имя свойства "undefined".

Вы в основном проверяете, существует ли пользователь, если нет, вы создаете пустой объект "на лету". Таким образом, ключ следующего уровня всегда будет доступен из объекта, который существует или пустой объект, но никогда не будет неопределенным.

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.

Существует также обработка минимальной библиотеки отличный типа породной, который делает все это для вас.

+3
07 июл. '18 в 8:32
источник

Питонический, рекурсивный и функциональный подход для распутывания произвольных деревьев 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)

где данные представляют собой список 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']}
]
+2
28 дек. '16 в 19:53
источник

Функция 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>
+1
28 авг. '17 в 11:25
источник

Мой stringjson происходит из PHP файла, но все же, я указываю здесь, в var. Когда я напрямую беру свой json в obj это ничего не показывает, поэтому я помещаю свой файл json как

var obj=JSON.parse(stringjson); поэтому после этого я получаю message obj и показываю в окне предупреждения, затем я получаю data которые являются массивом json, и сохраняю их в одну переменную ArrObj затем я читаю первый объект этого массива со значением ключа, таким как ArrObj[0].id

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

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

                alert(ArrObj[0].id);
0
04 апр. '19 в 8:51
источник

Здесь используется динамический подход - ваш "глубокий" ключ - это строковые 'items[1].name' (вы можете использовать обозначение массива [i] на любом уровне) - если ключ недействителен, возвращается undefined.

let deep = (o,k) => {
  return k.split('.').reduce((a,c,i) => {
    let m=c.match(/(.*?)\[(\d*)\]/);
    if(m && a!=null && a[m[1]]!=null) return a[m[1]][+m[2]];
    return a==null ? a: a[c];
  },o)
}

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

let deep = (o,k) => {
  return k.split('.').reduce((a,c,i) => {
    let m=c.match(/(.*?)\[(\d*)\]/);
    if(m && a!=null && a[m[1]]!=null) return a[m[1]][+m[2]];
    return a==null ? a: a[c];
  },o)
}

console.log( deep(data,'items[1].name') );
0
26 июн. '19 в 5:01
источник

Использование lodash было бы хорошим решением

Пример:

var object = { 'a': { 'b': { 'c': 3 } } };                                                                                               
_.get(object, 'a.b.c');                                                                                             
// => 3  
-1
27 сент. '17 в 12:31
источник

Посмотрите другие вопросы по меткам или Задайте вопрос