Me gustaría atravesar un árbol de objetos JSON, pero no puedo encontrar ninguna biblioteca para eso. No parece difícil, pero se siente como reinventar la rueda.
En XML hay muchos tutoriales que muestran cómo atravesar un árbol XML con DOM :(
javascript
json
Patsy Issa
fuente
fuente
Respuestas:
Si crees que jQuery es una exageración para una tarea tan primitiva, podrías hacer algo así:
fuente
this
valor de la función de destino, mientras queo
debería ser el primer parámetro de la función. Sin embargo, establecerlo enthis
(que sería latraverse
función) es un poco extraño, pero no es comoprocess
usar lathis
referencia de todos modos. Bien podría haber sido nulo./*jshint validthis: true */
arribafunc.apply(this,[i,o[i]]);
para evitar el errorW040: Possible strict violation.
causado por el uso dethis
traverse
función que rastrea la profundidad. Wenn llamando recursivamente agrega 1 al nivel actual.Un objeto JSON es simplemente un objeto Javascript. En realidad, eso es lo que JSON significa: notación de objetos JavaScript. Por lo tanto, atravesaría un objeto JSON, sin embargo, elegiría "atravesar" un objeto Javascript en general.
En ES2017 harías:
Siempre puedes escribir una función para descender recursivamente al objeto:
Este debería ser un buen punto de partida. Recomiendo encarecidamente utilizar métodos javascript modernos para tales cosas, ya que hacen que escribir dicho código sea mucho más fácil.
fuente
function traverse(jsonObj) { if(jsonObj && typeof jsonObj == "object" ) { ...
fuente
much better
?!!o[i] && typeof o[i] == 'object'
Hay una nueva biblioteca para atravesar datos JSON con JavaScript que admite muchos casos de uso diferentes.
https://npmjs.org/package/traverse
https://github.com/substack/js-traverse
Funciona con todo tipo de objetos JavaScript. Incluso detecta ciclos.
También proporciona la ruta de cada nodo.
fuente
Depende de lo que quieras hacer. Aquí hay un ejemplo de atravesar un árbol de objetos JavaScript, imprimir claves y valores a medida que avanza:
fuente
Si está atravesando una cadena JSON real , puede usar una función de reviver.
Al atravesar un objeto:
fuente
EDITAR : Todos los ejemplos a continuación en esta respuesta se han editado para incluir una nueva variable de ruta producida por el iterador según la solicitud de @ supersan . La variable de ruta es una matriz de cadenas donde cada cadena en la matriz representa cada clave a la que se accedió para obtener el valor iterado resultante del objeto fuente original. La variable de ruta se puede alimentar a la función / método get de lodash . O podría escribir su propia versión de lodash get que maneja solo matrices de esta manera:
EDITAR : Esta respuesta editada resuelve recorridos en bucle infinito.
Detener molestos recorridos de objetos infinitos
Esta respuesta editada aún proporciona uno de los beneficios adicionales de mi respuesta original, que le permite usar la función de generador proporcionada para usar una interfaz iterativa más limpia y simple (piense en usar
for of
bucles como enfor(var a of b)
dondeb
es iterable ya
es un elemento del iterable). ) Al usar la función de generador, además de ser una API más simple, también ayuda con la reutilización del código al hacer que no tenga que repetir la lógica de iteración en todas partes donde desee iterar profundamente en las propiedades de un objeto y también hace posiblebreak
salir de el bucle si desea detener la iteración antes.Una cosa que noté que no se ha abordado y que no está en mi respuesta original es que debe tener cuidado al atravesar objetos arbitrarios (es decir, cualquier conjunto "aleatorio"), porque los objetos JavaScript pueden ser auto-referenciados. Esto crea la oportunidad de tener recorridos en bucle infinito. Sin embargo, los datos JSON no modificados no pueden ser auto-referenciados, por lo que si está utilizando este subconjunto particular de objetos JS, no tiene que preocuparse por los recorridos de bucle infinito y puede consultar mi respuesta original u otras respuestas. Aquí hay un ejemplo de un recorrido sin fin (tenga en cuenta que no es un código ejecutable, porque de lo contrario se bloquearía la pestaña del navegador).
También en el objeto generador en mi ejemplo editado, opté por usar en
Object.keys
lugar defor in
que itera solo claves no prototipo en el objeto. Puede cambiar esto usted mismo si desea que se incluyan las claves prototipo. Vea mi sección de respuestas original a continuación para ambas implementaciones conObject.keys
yfor in
.Peor: esto hará un bucle infinito en objetos autorreferenciales:
Para salvarse de esto, puede agregar un conjunto dentro de un cierre, de modo que cuando se llama a la función por primera vez, comience a construir una memoria de los objetos que ha visto y no continúe la iteración una vez que se encuentre con un objeto ya visto. El siguiente fragmento de código hace eso y, por lo tanto, maneja casos de bucle infinito.
Mejor: este no será un bucle infinito en objetos autorreferenciales:
Respuesta original
Para obtener una forma más nueva de hacerlo si no le importa descartar IE y admitir principalmente navegadores más actuales (consulte la tabla es6 de kangax para ver la compatibilidad). Puede usar generadores es2015 para esto. He actualizado la respuesta de @ TheHippo en consecuencia. Por supuesto, si realmente desea el soporte de IE, puede usar el transpilador JavaScript de babel .
Si solo desea propiedades propias enumerables (básicamente propiedades de cadena no prototipo), puede cambiarlo para iterar usando
Object.keys
y unfor...of
bucle en su lugar:fuente
Quería usar la solución perfecta de @TheHippo en una función anónima, sin el uso de procesos y funciones de activación. Lo siguiente funcionó para mí, compartiendo para programadores novatos como yo.
fuente
La mayoría de los motores de Javascript no optimizan la recursividad de cola (esto podría no ser un problema si su JSON no está profundamente anidado), pero por lo general me equivoco con precaución y en su lugar hago iteraciones, por ejemplo
fuente
Mi guión:
Entrada JSON:
Llamada de función:
Salida según mi necesidad:
fuente
fuente
La mejor solución para mí fue la siguiente:
simple y sin usar ningún marco
fuente
Puede obtener todas las claves / valores y preservar la jerarquía con esto
Esta es una modificación en ( https://stackoverflow.com/a/25063574/1484447 )
fuente
fuente
He creado una biblioteca para atravesar y editar objetos JS profundamente anidados. Echa un vistazo a la API aquí: https://github.com/dominik791
También puedes jugar con la biblioteca de manera interactiva usando la aplicación de demostración: https://dominik791.github.io/obj-traverse-demo/
Ejemplos de uso: siempre debe tener un objeto raíz, que es el primer parámetro de cada método:
El segundo parámetro es siempre el nombre de la propiedad que contiene los objetos anidados. En el caso anterior sería
'children'
.El tercer parámetro es un objeto que utiliza para buscar objetos / objetos que desea encontrar / modificar / eliminar. Por ejemplo, si está buscando un objeto con una identificación igual a 1, pasará
{ id: 1}
como tercer parámetro.Y tu puedes:
findFirst(rootObj, 'children', { id: 1 })
para encontrar el primer objeto conid === 1
findAll(rootObj, 'children', { id: 1 })
para encontrar todos los objetos conid === 1
findAndDeleteFirst(rootObj, 'children', { id: 1 })
para eliminar el primer objeto coincidentefindAndDeleteAll(rootObj, 'children', { id: 1 })
para eliminar todos los objetos coincidentesreplacementObj
se usa como el último parámetro en dos últimos métodos:findAndModifyFirst(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
para cambiar el primer objeto encontrado conid === 1
el{ id: 2, name: 'newObj'}
findAndModifyAll(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
para cambiar todos los objetos conid === 1
el{ id: 2, name: 'newObj'}
fuente