J'aimerais parcourir une arborescence d'objets JSON, mais je ne trouve aucune bibliothèque pour cela. Cela ne semble pas difficile mais c'est comme réinventer la roue.
En XML, il y a tellement de tutoriels montrant comment parcourir une arborescence XML avec DOM :(
javascript
json
Patsy Issa
la source
la source
Réponses:
Si vous pensez que jQuery est un peu exagéré pour une tâche aussi primitive, vous pouvez faire quelque chose comme ça:
la source
this
valeur de la fonction cible, alors qu'ilo
devrait être le premier paramètre de la fonction. Le définir surthis
(ce qui serait latraverse
fonction) est cependant un peu étrange, mais ce n'est pas comme si vousprocess
utilisiez lathis
référence de toute façon. Cela aurait tout aussi bien pu être nul./*jshint validthis: true */
ci-dessusfunc.apply(this,[i,o[i]]);
pour éviter l'erreurW040: Possible strict violation.
causée par l'utilisation dethis
traverse
fonction qui suit la profondeur. Wenn appelant récursivement ajoute 1 au niveau actuel.Un objet JSON est simplement un objet Javascript. C'est en fait ce que signifie JSON: la notation d'objets JavaScript. Vous traverseriez donc un objet JSON comme vous choisiriez de "traverser" un objet Javascript en général.
Dans ES2017, vous feriez:
Vous pouvez toujours écrire une fonction pour descendre récursivement dans l'objet:
Cela devrait être un bon point de départ. Je recommande vivement d'utiliser des méthodes javascript modernes pour de telles choses, car elles facilitent beaucoup l'écriture de ce code.
la source
function traverse(jsonObj) { if(jsonObj && typeof jsonObj == "object" ) { ...
la source
much better
?!!o[i] && typeof o[i] == 'object'
Il existe une nouvelle bibliothèque pour parcourir les données JSON avec JavaScript qui prend en charge de nombreux cas d'utilisation différents.
https://npmjs.org/package/traverse
https://github.com/substack/js-traverse
Il fonctionne avec toutes sortes d'objets JavaScript. Il détecte même les cycles.
Il fournit également le chemin de chaque nœud.
la source
Tout dépends de ce que tu veux faire. Voici un exemple de parcours d'une arborescence d'objets JavaScript, d'impression de clés et de valeurs au fur et à mesure:
la source
Si vous parcourez une chaîne JSON réelle, vous pouvez utiliser une fonction reviver.
Lors de la traversée d'un objet:
la source
EDIT : Tous les exemples ci-dessous dans cette réponse ont été modifiés pour inclure une nouvelle variable de chemin fournie par l'itérateur conformément à la demande de @ supersan . La variable path est un tableau de chaînes où chaque chaîne du tableau représente chaque clé à laquelle on a accédé pour accéder à la valeur itérée résultante à partir de l'objet source d'origine. La variable path peut être introduite dans la fonction / méthode get de lodash . Ou vous pouvez écrire votre propre version de get de lodash qui ne gère que les tableaux comme ceci:
EDIT : Cette réponse modifiée résout des traversées en boucle infinies.
Arrêter les traversées d'objets infinis
Cette réponse modifiée fournit toujours l'un des avantages supplémentaires de ma réponse originale qui vous permet d'utiliser la fonction de générateur fournie afin d'utiliser une interface itérable plus propre et simple (pensez à utiliser des
for of
boucles comme dansfor(var a of b)
oùb
est un itérable eta
est un élément de l'itérable ). En utilisant la fonction de générateur en plus d'être une API plus simple, cela aide également à la réutilisation du code en évitant d'avoir à répéter la logique d'itération partout où vous souhaitez itérer en profondeur sur les propriétés d'un objet et cela permet également debreak
sortir de la boucle si vous souhaitez arrêter l'itération plus tôt.Une chose que je remarque et qui n'a pas été abordée et qui n'est pas dans ma réponse originale est que vous devez être prudent en parcourant des objets arbitraires (c'est-à-dire tout ensemble "aléatoire"), car les objets JavaScript peuvent être auto-référencés. Cela crée la possibilité d'avoir des traversées en boucle infinies. Les données JSON non modifiées ne peuvent cependant pas être auto-référencées, donc si vous utilisez ce sous-ensemble particulier d'objets JS, vous n'avez pas à vous soucier des traversées en boucle infinies et vous pouvez vous référer à ma réponse originale ou à d'autres réponses. Voici un exemple de parcours sans fin (notez que ce n'est pas un morceau de code exécutable, car sinon, il planterait l'onglet de votre navigateur).
Également dans l'objet générateur de mon exemple édité, j'ai choisi d'utiliser à la
Object.keys
place defor in
laquelle n'itère que des clés non prototypes sur l'objet. Vous pouvez l'échanger vous-même si vous souhaitez que les clés prototypes soient incluses. Voir ma section de réponse originale ci-dessous pour les deux implémentations avecObject.keys
etfor in
.Pire - Cela fera une boucle infinie sur les objets auto-référentiels:
Pour vous sauver de cela, vous pouvez ajouter un ensemble dans une fermeture, de sorte que lorsque la fonction est appelée pour la première fois, elle commence à créer une mémoire des objets qu'elle a vus et ne continue pas l'itération une fois qu'elle rencontre un objet déjà vu. L'extrait de code ci-dessous fait cela et gère donc des cas de boucle infinis.
Mieux - Ce ne sera pas une boucle infinie sur les objets auto-référentiels:
Réponse originale
Pour une nouvelle façon de le faire si cela ne vous dérange pas d'abandonner IE et de prendre en charge principalement les navigateurs plus récents (consultez le tableau es6 de kangax pour la compatibilité). Vous pouvez utiliser les générateurs es2015 pour cela. J'ai mis à jour la réponse de @ TheHippo en conséquence. Bien sûr, si vous voulez vraiment le support IE, vous pouvez utiliser le transpilateur JavaScript babel .
Si vous ne voulez que des propriétés énumérables propres (essentiellement des propriétés de chaîne non prototypes), vous pouvez le modifier pour itérer en utilisant
Object.keys
et unefor...of
boucle à la place:la source
Je voulais utiliser la solution parfaite de @TheHippo dans une fonction anonyme, sans utilisation de fonctions de processus et de déclenchement. Ce qui suit a fonctionné pour moi, le partage pour les programmeurs novices comme moi.
la source
La plupart des moteurs Javascript n'optimisent pas la récursivité de la queue (cela peut ne pas être un problème si votre JSON n'est pas profondément imbriqué), mais je me trompe généralement par prudence et je fais plutôt des itérations, par exemple
la source
Mon script:
Entrée JSON:
Appel de fonction:
Sortie selon mon besoin:
la source
la source
La meilleure solution pour moi était la suivante:
simple et sans utiliser de framework
la source
Vous pouvez obtenir toutes les clés / valeurs et préserver la hiérarchie avec ceci
Ceci est une modification sur ( https://stackoverflow.com/a/25063574/1484447 )
la source
la source
J'ai créé une bibliothèque pour parcourir et modifier des objets JS imbriqués en profondeur. Découvrez l'API ici: https://github.com/dominik791
Vous pouvez également jouer avec la bibliothèque de manière interactive en utilisant l'application de démonstration: https://dominik791.github.io/obj-traverse-demo/
Exemples d'utilisation: Vous devez toujours avoir un objet racine qui est le premier paramètre de chaque méthode:
Le deuxième paramètre est toujours le nom de la propriété qui contient les objets imbriqués. Dans le cas ci-dessus, ce serait
'children'
.Le troisième paramètre est un objet que vous utilisez pour rechercher les objets / objets que vous souhaitez rechercher / modifier / supprimer. Par exemple, si vous recherchez un objet avec un id égal à 1, vous le passerez
{ id: 1}
comme troisième paramètre.Et tu peux:
findFirst(rootObj, 'children', { id: 1 })
pour trouver le premier objet avecid === 1
findAll(rootObj, 'children', { id: 1 })
pour trouver tous les objets avecid === 1
findAndDeleteFirst(rootObj, 'children', { id: 1 })
pour supprimer le premier objet correspondantfindAndDeleteAll(rootObj, 'children', { id: 1 })
pour supprimer tous les objets correspondantsreplacementObj
est utilisé comme dernier paramètre dans deux dernières méthodes:findAndModifyFirst(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
pour changer le premier objet trouvé avecid === 1
le{ id: 2, name: 'newObj'}
findAndModifyAll(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
pour changer tous les objets avecid === 1
le{ id: 2, name: 'newObj'}
la source