Objetos de acceso / proceso (anidados), matrices o JSON


Tengo una estructura de datos anidada que contiene objetos y matrices. ¿Cómo puedo extraer la información, es decir, acceder a valores (o claves) específicos o múltiples?

Por ejemplo:

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

¿Cómo podría acceder al name del segundo elemento en items?

Author: AndrewL, 2012-08-12

20 answers

Preliminares

JavaScript solo tiene un tipo de datos que puede contener múltiples valores: Object . Un Array es una forma especial de objeto.

Los objetos(simples) tienen la forma

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

Los arrays tienen la forma

[value, value, ...]

Tanto los arrays como los objetos exponen una estructura key -> value. Las claves en un array deben ser numéricas, mientras que cualquier cadena puede ser usada como clave en objetos. Los pares clave-valor también se llaman "propiedades".

Se puede acceder a las propiedades usando notación de puntos

const value = obj.someProperty;

O notación entre corchetes , si el nombre de la propiedad no sería un nombre de identificador válido de JavaScript [spec], o el nombre es el valor de una variable:

// 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];

Por esa razón, solo se puede acceder a los elementos del array usando la notación entre corchetes:

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

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

Espera... ¿qué hay de JSON?

JSON es una representación textual de datos, al igual que XML, YAML, CSV y otros. Para trabajar con tales datos, primero tiene que convertirse a tipos de datos JavaScript, es decir, arrays y objetos (y cómo trabajar con ellos se acaba de explicar). ¿Cómo analizar JSON se explica en la pregunta Analizar JSON en JavaScript? .

Material de lectura adicional

Cómo acceder a arrays y objetos es un conocimiento fundamental de JavaScript y por lo tanto es recomendable leer la Guía MDN JavaScript , especialmente la secciones



Acceso a estructuras de datos anidadas

Una estructura de datos anidada es una matriz u objeto que se refiere a otras matrices u objetos, es decir, sus valores son matrices u objetos. Se puede acceder a dichas estructuras aplicando consecutivamente la notación de punto o corchete.

Aquí hay un ejemplo:

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

Supongamos que queremos acceder al name del segundo elemento.

Aquí es cómo podemos hacerlo paso a paso:

Como podemos ver data es un objeto, por lo tanto podemos acceder a sus propiedades usando la notación de puntos. La propiedad items se accede de la siguiente manera:

data.items

El valor es un array, para acceder a su segundo elemento, tenemos que usar la notación entre corchetes:

data.items[1]

Este valor es un objeto y usamos la notación de puntos de nuevo para acceder al name propiedad. Así que finalmente obtenemos:

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

Alternativamente, podríamos haber utilizado la notación entre corchetes para cualquiera de las propiedades, especialmente si el nombre contenía caracteres que lo habrían hecho inválido para el uso de la notación de puntos:

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

Estoy intentando acceder a una propiedad pero solo obtengo undefined de vuelta?

La mayor parte del tiempo cuando se obtiene undefined, el objeto/matriz simplemente no tiene una propiedad con ese nombre.

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

Uso console.log o console.dir e inspeccionar la estructura del objeto / matriz. La propiedad a la que intenta acceder puede estar definida en un objeto / array anidado.

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

¿Qué pasa si los nombres de las propiedades son dinámicos y no los conozco de antemano?

Si los nombres de propiedad son desconocidos o queremos acceder a todas las propiedades de un objeto / elementos de un array, podemos utilizar el for...in [MDN] bucle para objetos y el for [MDN] bucle para que los arrays iteren sobre todas las propiedades / elementos.

Objetos

Para iterar sobre todas las propiedades de data, podemos iterar sobre el objeto de la siguiente manera:

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
}

Dependiendo de dónde viene el objeto (y lo que desea hacer), es posible que tenga que probar en cada iteración si la propiedad es realmente una propiedad del objeto, o es una propiedad heredada. Puedes hacer esto con Object#hasOwnProperty [MDN].

Como alternativa a for...in con hasOwnProperty, puede utilizar Object.keys [MDN] para obtener un array de nombres de propiedad:

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

Arrays

Para iterar sobre todos los elementos de la data.items array , usamos un bucle 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`.
}

También se podría usar for...in para iterar sobre matrices, pero hay razones por las que esto debe evitarse: ¿Por qué es 'for(var item in list)' con arrays considerado mala práctica en JavaScript?.

Con el creciente soporte del navegador de ECMAScript 5, el método array forEach [MDN] se convierte en una alternativa interesante también:

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

En entornos de apoyo ES2015 (ES6), también puede utilizar el for...of [MDN] lazo, que no sólo funciona para las matrices, pero para cualquier iterable:

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

En cada iteración, for...of nos da directamente el siguiente elemento del iterable, no hay "índice" para acceder o usar.


¿Qué pasa si la "profundidad" de la estructura de datos es desconocida para mí?

Además de las claves desconocidas, la "profundidad" de la estructura de datos (es decir, cuántos objetos anidados) que tiene, también podría ser desconocida. La forma de acceder a las propiedades profundamente anidadas suele depender de la estructura de datos exacta.

Pero si la estructura de datos contiene patrones repetidos, por ejemplo, el representación de un árbol binario, la solución incluye típicamente a recursivamente [Wikipedia] acceda a cada nivel de la estructura de datos.

Aquí hay un ejemplo para obtener el primer nodo hoja de un árbol binario:

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

Una forma más genérica de acceder a una estructura de datos anidada con claves y profundidad desconocidas es probar el tipo del valor y actuar en consecuencia.

Aquí hay un ejemplo que agrega todos valores primitivos dentro de una estructura de datos anidada en una matriz (suponiendo que no contenga ninguna función). Si nos encontramos con un objeto (o matriz) simplemente llamamos toArray de nuevo en ese valor (llamada recursiva).

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


Ayudantes

Dado que la estructura de un objeto o array complejo no es necesariamente obvia, podemos inspeccionar el valor en cada paso para decidir cómo avanzar más. console.log [MDN] y console.dir [MDN] nos ayudan a hacer esto. Por ejemplo (salida de la consola Chrome):

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

Aquí vemos que ese data.items es una matriz con dos elementos que son ambos objetos. En Chrome console, los objetos pueden incluso expandirse e inspeccionarse inmediatamente.

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

Esto nos dice que data.items[1] es un objeto, y después de expandirlo vemos que tiene tres propiedades, id, name y __proto__. Esta última es una propiedad interna utilizada para cadena prototipo del objeto. Sin embargo, la cadena de prototipos y la herencia están fuera del alcance de esta respuesta.

 904
Author: Felix Kling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-16 19:10:23

Se puede acceder de esta manera

data.items[1].name

O

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

Ambos caminos son iguales.

 50
Author: vitmalina,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-14 03:29:19

En caso de que esté tratando de acceder a un item desde la estructura de ejemplo por id o name, sin saber su posición en la matriz, la forma más fácil de hacerlo sería usar subrayado.js biblioteca:

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

Desde mi experiencia, usar funciones de orden superior en lugar de bucles for o for..in resulta en un código que es más fácil de razonar y, por lo tanto, más fácil de mantener.

Solo mis 2 centavos.

 22
Author: holographic-principle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-13 10:25:38

A veces, acceder a un objeto anidado usando una cadena puede ser deseable. El enfoque simple es el primer nivel, por ejemplo

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

Pero esto a menudo no es el caso con json complejo. A medida que json se vuelve más complejo, los enfoques para encontrar valores dentro del json también se vuelven complejos. Un enfoque recursivo para navegar por el json es el mejor, y cómo se aproveche esa recursividad dependerá del tipo de datos que se busquen. Si hay declaraciones condicionales involucradas, un json search puede ser una buena herramienta para usar.

Si la propiedad a la que se accede ya es conocida, pero la ruta es compleja, por ejemplo en este objeto

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

Y usted sabe que desea obtener el primer resultado de la matriz en el objeto, tal vez le gustaría utilizar

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

Sin embargo, eso causará una excepción ya que no hay ninguna propiedad de object con ese nombre. La solución para poder usar esto sería aplanar el aspecto de árbol del objeto. Esto se puede hacer recursivamente.

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

Ahora, el objeto complejo se puede aplanar

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

Aquí es un jsFiddle Demo de este enfoque se utiliza.

 15
Author: Travis J,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:54

Objects and arrays tiene muchos métodos incorporados que pueden ayudarlo con el procesamiento de datos.

Nota: en muchos de los ejemplos estoy usando funciones de flecha. Son similares a las expresiones de función , pero enlazan el valor this léxicamente.

Object.keys(), Object.values() (ES 2017) y Object.entries() (ES 2017)

Object.keys() devuelve una matriz de claves del objeto, Object.values() devuelve una matriz de valores del objeto, y Object.entries() devuelve una matriz de las claves del objeto y los valores correspondientes en un formato [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() con un bucle for-of y asignación de desestructuración

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

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

Es muy conveniente iterar el resultado de Object.entries() con un bucle for-of y asignación de desestructuración.

El bucle For-of le permite iterar elementos de matriz. La sintaxis es for (const element of array) (podemos reemplazar const con var o let, pero es mejor usar const si no lo hacemos intención de modificar element).

La asignación de desestructuración le permite extraer valores de una matriz o un objeto y asignarlos a variables. En este caso const [key, value] significa que en lugar de asignar el array [key, value] a element, asignamos el primer elemento de ese array a key y el segundo elemento a value. Es equivalente a esto:

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

Como puedes ver, la desestructuración hace esto mucho más simple.

Array.prototype.every() y Array.prototype.some()

El every() method returns true if the specified callback function returns true for every element of the array. El método some() devuelve true si la función callback especificada devuelve true para algún elemento (al menos un).

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() y Array.prototype.filter()

Los métodos find() devuelven el primer elemento que satisface la función callback proporcionada. El método filter() devuelve un array de todos los elementos que satisfacen la función callback proporcionada.

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

El método map() devuelve una matriz con los resultados de llamar a una función de devolución de llamada proporcionada en los elementos de la matriz.

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

El método reduce() reduce una matriz a un solo valor llamando a la función de devolución de llamada proporcionada con dos elemento.

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

El método reduce() toma un segundo parámetro opcional, que es el valor inicial. Esto es útil cuando la matriz en la que se llama reduce() can tiene cero o uno elementos. Por ejemplo, si queremos crear una función sum() que toma una matriz como argumento y devuelve la suma de todos los elementos, podríamos escribir así:

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
 12
Author: Michał Perłakowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-22 18:38:41

Esta pregunta es bastante antigua, así como una actualización contemporánea. Con el inicio de ES2015 hay alternativas para obtener los datos que necesita. Ahora hay una característica llamada objeto de desestructuración para acceder a los objetos anidados.

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

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

console.log(secondName);

El ejemplo anterior crea una variable llamada secondName a partir de la clave name de un array llamado items, el solitario , dice omitir el primer objeto del array.

En particular, probablemente es excesivo para este ejemplo, como simple array acccess es más fácil de leer, pero es útil cuando se rompen objetos en general.

Esta es una introducción muy breve a su caso de uso específico, la desestructuración puede ser una sintaxis inusual para acostumbrarse al principio. Recomiendo leer La documentación de Asignación Desestructuring de Mozilla para obtener más información.

 8
Author: Alex KeySmith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-25 09:32:21

Usar JSONPath sería una de las soluciones más flexibles si está dispuesto a incluir una biblioteca: https://github.com/s3u/JSONPath (nodo y navegador)

Para su caso de uso la ruta json sería:

$..items[1].name

Así que:

var secondName = jsonPath.eval(data, "$..items[1].name");
 6
Author: Andrejs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-26 12:43:46

Prefiero jQuery. Es más limpio y fácil de leer.

 $.each($.parseJSON(data), function (key, value) {
    alert(value.<propertyname>);
});
 5
Author: Rudy Hinojosa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-24 15:55:02

Para acceder a un atributo anidado, debe especificar su nombre y luego buscar a través del objeto.

Si ya conoce la ruta exacta, entonces puede codificarla en su script de la siguiente manera:

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

Estos también funcionan -

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

Cuando usted no sabe el nombre exacto de antemano, o un usuario es el que proporciona el nombre para usted. A continuación, se requiere una búsqueda dinámica a través de la estructura de datos. Algunos sugirieron aquí que la búsqueda se puede hacer usando un bucle for, pero hay una manera muy sencilla de atravesar un camino usando 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)

La ruta es una forma de decir: Primero toma el objeto con key items, que resulta ser un array. Luego tome el elemento 1-st (matrices de índice 0). Por último, tome el objeto con clave name en ese elemento de matriz, que pasa a ser la cadena bar.

Si tienes un camino muy largo, incluso puedes usar String.split para hacer todo esto más fácil -

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

Esto es simplemente JavaScript, sin usar ningún librerías de terceros como jQuery o lodash.

 4
Author: Evgeny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-15 10:17:33

Si está buscando uno o más objetos que cumplan con ciertos criterios, tiene algunas opciones usando 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:""});

También hay un single y un singleOrDefault funcionan como first y firstOrDefault respectivamente. La única diferencia es que lanzarán si más de un partido se encuentra.

Para mayor explicación de query-js puede comenzar con este post

 3
Author: Rune FS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-18 08:35:05

Puedes usar la función lodash _get:

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

_.get(object, 'a[0].b.c');
// => 3
 3
Author: Sergey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-03 04:24:27

La forma de subrayado js

Que es una biblioteca JavaScript que proporciona un montón de útiles ayudantes functional programming sin extender ningún objeto incorporado.

Solución:

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);
}
 2
Author: Mohan Dere,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-13 10:50:46

No creo que el interrogador solo se refiera a un objeto anidado de nivel, por lo que presento la siguiente demostración para demostrar cómo acceder al nodo del objeto json profundamente anidado. Bien, vamos a encontrar el nodo con 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>
 1
Author: dabeng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-22 09:00:32

Vieja pregunta pero como nadie mencionó lodash (solo subrayado).

En caso de que ya esté utilizando lodash en su proyecto, creo que una forma elegante de hacer esto en un ejemplo complejo:

Opt 1

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

Igual que:

Opt 2

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

La diferencia entre la primera y la segunda opción es que en el Opt 1 si tiene una de las propiedades faltantes (indefinidas) en la ruta no obtiene un error, le devuelve la tercera parámetro.

Para el filtro de matriz lodash tiene _.find() pero prefiero usar el filter() regular. Pero sigo pensando que el método anterior _.get() es súper útil cuando se trabaja con datos realmente complejos. Me enfrenté en el pasado API realmente complejas y fue útil!

Espero que pueda ser útil para quien está buscando opciones para manipular datos realmente complejos que el título implica.

 1
Author: Ventura,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-01 11:46:35

Accediendo dinámicamente a objetos de varios niveles.

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

Violín de trabajo: https://jsfiddle.net/andreitodorut/3mws3kjL /

 1
Author: Andrei Todorut,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-27 20:39:14
var ourStorage = {


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

O

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

Básicamente, use un punto entre cada descendiente que se despliega debajo de él y cuando tenga nombres de objetos hechos de dos cadenas, debe usar la notación ["obj Name"]. De lo contrario, solo un punto sería suficiente;

Fuente: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-objects

Para añadir a esto, el acceso a los arrays anidados sucedería de la siguiente manera:

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"

Fuente: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays/

 1
Author: Riddick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-19 23:53:18

Un enfoque pitónico, recursivo y funcional para desentrañar árboles JSON arbitrarios:

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)

Donde data es una lista de python (analizada a partir de una cadena de texto 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']}
]
 0
Author: pX0r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-29 07:55:36

La función grep de jQuery le permite filtrar a través de una matriz:

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>
 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-28 11:25:30

Por si acaso, cualquiera que visite esta pregunta en 2017 o más tarde y busque una forma fácil de recordar , aquí hay una elaborada publicación de blog sobre Acceder a Objetos Anidados en JavaScript sin ser engañado por

No se puede leer la propiedad ' foo ' de undefined error

1. El patrón de acceso a objetos anidados de Oliver Steele

La forma más fácil y limpia es usar el patrón de acceso a objetos anidados de Oliver Steele

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

Con esta notación, nunca te toparás con

No se puede leer la propiedad 'name' de undefined .

Básicamente se comprueba si el usuario existe, si no, se crea un objeto vacío sobre la marcha. De esta manera, la siguiente clave de nivel siempre se accederá desde un objeto que existe o desde un objeto vacío, pero nunca desde undefined.

2. Acceda A Objetos Anidados Usando Array Reduce

Para poder acceder a los arrays anidados, puede escribir su propio array 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.

También Hay un excelente manejo de tipos minimal library typy que hace todo esto por usted.

 0
Author: Dinesh Pandiyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-09 04:01:48

Usar lodash sería una buena solución

Ex:

var object = { 'a': { 'b': { 'c': 3 } } };                                                                                               
_.get(object, 'a.b.c');                                                                                             
// => 3  
 -1
Author: pradeep gowda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-27 12:34:15