J'ai une structure de données imbriquée contenant des objets et des tableaux. Comment puis-je extraire les informations, c'est-à-dire accéder à une ou plusieurs valeurs (ou clés) spécifiques ou multiples?
Par exemple:
var data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
Comment puis-je accéder name
au deuxième élément de items
?
javascript
arrays
object
nested
data-manipulation
Felix Kling
la source
la source
Réponses:
Préliminaires
JavaScript n'a qu'un seul type de données qui peut contenir plusieurs valeurs: Objet . Un tableau est une forme spéciale d'objet.
(Ordinaire) Les objets ont la forme
Les tableaux ont la forme
Les tableaux et les objets exposent une
key -> value
structure. Les clés d'un tableau doivent être numériques, tandis que n'importe quelle chaîne peut être utilisée comme clé dans des objets. Les paires clé-valeur sont également appelées "propriétés" .Les propriétés sont accessibles soit en utilisant la notation par points
ou la notation entre crochets , si le nom de la propriété ne serait pas un nom d'identifiant JavaScript valide [spéc] , ou si le nom est la valeur d'une variable:
Pour cette raison, les éléments du tableau ne sont accessibles qu'en utilisant la notation entre crochets:
Attendez ... et JSON?
JSON est une représentation textuelle des données, tout comme XML, YAML, CSV et autres. Pour travailler avec de telles données, elles doivent d'abord être converties en types de données JavaScript, c'est-à-dire des tableaux et des objets (et comment travailler avec ceux-ci vient d'être expliqué). Comment analyser JSON est expliqué dans la question Analyser JSON en JavaScript? .
Autres lectures
Comment accéder aux tableaux et aux objets est une connaissance fondamentale de JavaScript et il est donc conseillé de lire le guide JavaScript MDN , en particulier les sections
Accès aux structures de données imbriquées
Une structure de données imbriquée est un tableau ou un objet qui fait référence à d'autres tableaux ou objets, c'est-à-dire que ses valeurs sont des tableaux ou des objets. De telles structures sont accessibles en appliquant consécutivement la notation par points ou par crochets.
Voici un exemple:
Supposons que nous voulons accéder
name
au deuxième élément.Voici comment nous pouvons le faire étape par étape:
Comme nous pouvons le voir
data
est un objet, donc nous pouvons accéder à ses propriétés en utilisant la notation par points. Laitems
propriété est accessible comme suit:La valeur est un tableau, pour accéder à son deuxième élément, nous devons utiliser la notation entre crochets:
Cette valeur est un objet et nous utilisons à nouveau la notation par points pour accéder à la
name
propriété. Nous obtenons donc finalement:Alternativement, nous aurions pu utiliser la notation entre crochets pour l'une des propriétés, surtout si le nom contenait des caractères qui l'auraient rendu invalide pour l'utilisation de la notation par points:
J'essaie d'accéder à une propriété mais je ne
undefined
reviens que?La plupart du temps, lorsque vous obtenez
undefined
, l'objet / tableau n'a tout simplement pas de propriété avec ce nom.Utilisez
console.log
ouconsole.dir
et inspectez la structure de l'objet / du tableau. La propriété à laquelle vous essayez d'accéder peut être réellement définie sur un objet / tableau imbriqué.Que faire si les noms de propriété sont dynamiques et que je ne les connais pas au préalable?
Si les noms de propriété sont inconnus ou si nous voulons accéder à toutes les propriétés d'un objet / éléments d'un tableau, nous pouvons utiliser la boucle
for...in
[MDN] pour les objets et la bouclefor
[MDN] pour les tableaux pour itérer sur toutes les propriétés / éléments.Objets
Pour itérer sur toutes les propriétés de
data
, nous pouvons itérer sur l' objet comme ceci:Selon d'où vient l'objet (et ce que vous voulez faire), vous devrez peut-être tester à chaque itération si la propriété est vraiment une propriété de l'objet ou une propriété héritée. Vous pouvez le faire avec
Object#hasOwnProperty
[MDN] .Comme alternative à
for...in
withhasOwnProperty
, vous pouvez utiliserObject.keys
[MDN] pour obtenir un tableau de noms de propriétés :Tableaux
Pour parcourir tous les éléments du
data.items
tableau , nous utilisons unefor
boucle:On pourrait également utiliser
for...in
pour itérer sur les tableaux, mais il y a des raisons pour lesquelles cela devrait être évité: Pourquoi est-ce que 'pour (élément var dans la liste)' avec des tableaux est considéré comme une mauvaise pratique en JavaScript? .Avec la prise en charge croissante des navigateurs d'ECMAScript 5, la méthode de tableau
forEach
[MDN] devient également une alternative intéressante:Dans les environnements prenant en charge ES2015 (ES6), vous pouvez également utiliser la boucle [MDN] , qui fonctionne non seulement pour les tableaux, mais pour tout élément itérable :
for...of
Dans chaque itération,
for...of
nous donne directement l'élément suivant de l'itérable, il n'y a pas d '"index" à accéder ou à utiliser.Et si la "profondeur" de la structure de données m'est inconnue?
En plus des clés inconnues, la "profondeur" de la structure de données (c'est-à-dire le nombre d'objets imbriqués) qu'elle possède peut également être inconnue. La façon d'accéder aux propriétés profondément imbriquées dépend généralement de la structure exacte des données.
Mais si la structure de données contient des motifs répétitifs, par exemple la représentation d'un arbre binaire, la solution comprend généralement l' accès récursif [Wikipedia] à chaque niveau de la structure de données.
Voici un exemple pour obtenir le premier nœud feuille d'un arbre binaire:
Afficher l'extrait de code
Un moyen plus générique d'accéder à une structure de données imbriquée avec des clés et une profondeur inconnues consiste à tester le type de la valeur et à agir en conséquence.
Voici un exemple qui ajoute toutes les valeurs primitives à l'intérieur d'une structure de données imbriquée dans un tableau (en supposant qu'elle ne contient aucune fonction). Si nous rencontrons un objet (ou un tableau), nous appelons simplement à
toArray
nouveau sur cette valeur (appel récursif).Afficher l'extrait de code
Aides
Étant donné que la structure d'un objet ou d'un tableau complexe n'est pas nécessairement évidente, nous pouvons inspecter la valeur à chaque étape pour décider comment aller plus loin.
console.log
[MDN] etconsole.dir
[MDN] nous aident à le faire. Par exemple (sortie de la console Chrome):Ici, nous voyons que c'est
data.items
un tableau avec deux éléments qui sont tous deux des objets. Dans la console Chrome, les objets peuvent même être développés et inspectés immédiatement.Cela nous dit que
data.items[1]
est un objet, et après l' avoir étendu , nous voyons qu'il a trois propriétés,id
,name
et__proto__
. Ce dernier est une propriété interne utilisée pour la chaîne prototype de l'objet. La chaîne de prototype et l'héritage sont cependant hors de portée pour cette réponse.la source
let object = {a: 1, b: 2, c: { a: 3, b: 4 }};
, cela renvoie un tableau contenant un tableau pour chaque objet imbriqué, dans ce cas,[ 1, 2, [ 3, 4 ] ]
ne serait-il pas préférable d'utiliser concat dans l'appel récursif au lieu de pousser? (exigeant que le résultat soit mutable)Vous pouvez y accéder de cette façon
ou
Les deux façons sont égales.
la source
Dans le cas où vous essayez d'accéder à un à
item
partir de la structure d'exemple parid
ouname
, sans connaître sa position dans le tableau, la façon la plus simple de le faire serait d'utiliser la bibliothèque underscore.js :D'après mon expérience, l'utilisation de fonctions d'ordre supérieur au lieu de
for
ou defor..in
boucles aboutit à un code plus facile à raisonner et donc plus facile à gérer.Juste mes 2 cents.
la source
Les objets et les tableaux disposent de nombreuses méthodes intégrées qui peuvent vous aider à traiter les données.
Remarque: dans de nombreux exemples, j'utilise des fonctions fléchées . Ils sont similaires aux expressions de fonction , mais ils lient la
this
valeur lexicalement.Object.keys()
,Object.values()
(ES 2017) etObject.entries()
(ES 2017)Object.keys()
renvoie un tableau de clés d'objet,Object.values()
renvoie un tableau de valeurs d'objet etObject.entries()
renvoie un tableau de clés d'objet et les valeurs correspondantes dans un format[key, value]
.Object.entries()
avec une boucle for-of et une affectation destructuranteIl est très pratique d'itérer le résultat de
Object.entries()
avec une boucle for-of et une affectation de déstructuration .La boucle For-of vous permet d'itérer les éléments du tableau. La syntaxe est
for (const element of array)
(nous pouvons remplacerconst
parvar
oulet
, mais il vaut mieux utiliserconst
si nous n'avons pas l'intention de modifierelement
).L'affectation de déstructuration vous permet d'extraire des valeurs d'un tableau ou d'un objet et de les affecter à des variables. Dans ce cas, cela
const [key, value]
signifie qu'au lieu d'affecter le[key, value]
tableau àelement
, nous attribuons le premier élément de ce tableau àkey
et le deuxième élément àvalue
. C'est équivalent à ceci:Comme vous pouvez le voir, la déstructuration rend cela beaucoup plus simple.
Array.prototype.every()
etArray.prototype.some()
La
every()
méthode renvoietrue
si la fonction de rappel spécifiée renvoietrue
pour chaque élément du tableau. Lasome()
méthode renvoietrue
si la fonction de rappel spécifiée renvoietrue
pour certains (au moins un) élément.Array.prototype.find()
etArray.prototype.filter()
Les
find()
méthodes retournent le premier élément qui satisfait la fonction de rappel fournie. Lafilter()
méthode renvoie un tableau de tous les éléments qui satisfait la fonction de rappel fournie.Array.prototype.map()
La
map()
méthode renvoie un tableau avec les résultats de l'appel d'une fonction de rappel fournie sur les éléments du tableau.Array.prototype.reduce()
La
reduce()
méthode réduit un tableau à une seule valeur en appelant la fonction de rappel fournie avec deux éléments.La
reduce()
méthode prend un deuxième paramètre facultatif, qui est la valeur initiale. Ceci est utile lorsque le tableau sur lequel vous appelezreduce()
peut avoir zéro ou un élément. Par exemple, si nous voulions créer une fonctionsum()
qui prend un tableau comme argument et retourne la somme de tous les éléments, nous pourrions l'écrire comme ça:la source
Object.keys(data["items"]).forEach(function(key) { console.log(data["items"][key].id); console.log(data["items"][key].name); });
Parfois, l'accès à un objet imbriqué à l'aide d'une chaîne peut être souhaitable. L'approche simple est le premier niveau, par exemple
Mais ce n'est souvent pas le cas avec json complexe. À mesure que json devient plus complexe, les approches pour trouver des valeurs à l'intérieur du json deviennent également complexes. Une approche récursive pour naviguer dans le json est la meilleure, et la manière dont cette récursivité est exploitée dépendra du type de données recherchées. S'il y a des instructions conditionnelles impliquées, une recherche json peut être un bon outil à utiliser.
Si la propriété en cours d'accès est déjà connue, mais que le chemin est complexe, par exemple dans cet objet
Et vous savez que vous voulez obtenir le premier résultat du tableau dans l'objet, vous voudrez peut-être utiliser
Cependant, cela provoquera une exception car il n'existe aucune propriété d'objet portant ce nom. La solution pour pouvoir l'utiliser serait d'aplatir l'aspect arborescent de l'objet. Cela peut être fait de manière récursive.
Maintenant, l'objet complexe peut être aplati
Voici une
jsFiddle Demo
de cette approche utilisée.la source
obj["arr[0].name"]
place deobj.arr[0].name
? Vous avez à peine besoin / envie de traiter des objets aplatis, sauf pour la sérialisation.Cette question est assez ancienne, donc comme une mise à jour contemporaine. Avec le début de ES2015, il existe des alternatives pour obtenir les données dont vous avez besoin. Il existe maintenant une fonctionnalité appelée déstructuration d'objet pour accéder aux objets imbriqués.
L'exemple ci-dessus crée une variable appelée à
secondName
partir de laname
clé d'un tableau appeléitems
, le seul,
dit ignorer le premier objet du tableau.Notamment, il est probablement exagéré pour cet exemple, car l'accès aux tableaux simples est plus facile à lire, mais il s'avère utile lors de la séparation des objets en général.
Il s'agit d'une introduction très brève à votre cas d'utilisation spécifique, la déstructuration peut être une syntaxe inhabituelle à laquelle s'habituer au début. Je vous recommande de lire la documentation de Destructuring Assignment de Mozilla pour en savoir plus.
la source
Pour accéder à un attribut imbriqué, vous devez spécifier son nom, puis rechercher dans l'objet.
Si vous connaissez déjà le chemin exact, vous pouvez le coder en dur dans votre script comme ceci:
cela fonctionne aussi -
Lorsque vous ne connaissez pas le nom exact à l'avance, ou qu'un utilisateur est celui qui vous fournit le nom. Une recherche dynamique dans la structure de données est alors requise. Certains ont suggéré ici que la recherche peut être effectuée à l'aide d'une
for
boucle, mais il existe un moyen très simple de parcourir un chemin à l'aide deArray.reduce
.Le chemin est une façon de dire: Prenez d'abord l'objet avec la clé
items
, qui se trouve être un tableau. Ensuite, prenez l'1
élément -st (0 tableaux d'index). Prenez en dernier l'objet avec la cléname
dans cet élément de tableau, qui se trouve être la chaînebar
.Si vous avez un très long chemin, vous pourriez même utiliser
String.split
pour rendre tout cela plus facile -Il s'agit simplement de JavaScript, sans utiliser de bibliothèques tierces comme jQuery ou lodash.
la source
ou
Fondamentalement, utilisez un point entre chaque descendant qui se déroule en dessous et lorsque vous avez des noms d'objets composés de deux chaînes, vous devez utiliser la notation ["nom obj"]. Sinon, un simple point suffirait;
Source: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-objects
pour ajouter à cela, l'accès aux tableaux imbriqués se produirait comme suit:
Source: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays/
Un autre document plus utile décrivant la situation ci-dessus: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics#Bracket_notation
Accès à la propriété via la marche par points: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation
la source
Vous pouvez utiliser la
lodash _get
fonction:la source
L'utilisation de JSONPath serait l'une des solutions les plus flexibles si vous souhaitez inclure une bibliothèque: https://github.com/s3u/JSONPath (nœud et navigateur)
Pour votre cas d'utilisation, le chemin json serait:
donc:
la source
Juste au cas où quelqu'un visiterait cette question en 2017 ou plus tard et chercherait un moyen facile à retenir , voici un article de blog élaboré sur l' accès aux objets imbriqués en JavaScript sans être embrouillé par
Impossible de lire la propriété 'foo' d'une erreur non définie
1. Modèle d'accès aux objets imbriqués d'Oliver Steele
Le moyen le plus simple et le plus propre consiste à utiliser le modèle d'accès aux objets imbriqués d'Oliver Steele
Avec cette notation, vous ne rencontrerez jamais
Impossible de lire la propriété 'nom' non définie .
Vous vérifiez essentiellement si l'utilisateur existe, sinon, vous créez un objet vide à la volée. De cette façon, la clé de niveau suivant sera toujours accessible à partir d'un objet qui existe ou d'un objet vide , mais jamais à partir d'un indéfini.
2. Accéder aux objets imbriqués à l'aide de Array Reduce
Pour pouvoir accéder aux tableaux imbriqués, vous pouvez écrire votre propre utilitaire de réduction de tableau.
Il existe également un excellent type de gestion de type de bibliothèque minimale qui fait tout cela pour vous.
la source
((user || {}).address || new Array(3))[1].name
...[1].bar
cela entraînerait une erreur si l'élément1
n'existait pas. Mais c'est aussi le cas pour....foo.bar
sifoo
n'existait pas. Vous devez également "garder" l'accès1
, tout comme vous "gardez" tout autre accès à la propriété. Un tableau n'est qu'un objet. Un "élément de tableau" n'est qu'une propriété. Correctement appliqué, il le serait(((user || {}).address || {})[1] || {}).name
.Je préfère JQuery. C'est plus propre et facile à lire.
la source
Accès dynamique à un objet à plusieurs niveaux.
Violon de travail: https://jsfiddle.net/andreitodorut/3mws3kjL/
la source
Si vous recherchez un ou plusieurs objets qui répondent à certains critères, vous avez quelques options en utilisant query-js
Il y a aussi un
single
et unsingleOrDefault
qui fonctionnent commefirst
etfirstOrDefault
respectivement. La seule différence est qu'ils lanceront si plus d'une correspondance est trouvée.pour plus d'explications sur query-js, vous pouvez commencer avec ce post
la source
The Underscore js Way
Qui est une bibliothèque JavaScript qui fournit toute une panoplie d'
functional programming
aides utiles sans étendre aucun objet intégré.Solution:
la source
Vieille question mais comme personne n'a mentionné lodash (juste souligner).
Dans le cas où vous utilisez déjà lodash dans votre projet, je pense qu'une manière élégante de le faire dans un exemple complexe:
Opt 1
pareil que:
Opt 2
La différence entre la première et la deuxième option est que dans l' Opt 1 si vous avez une des propriétés manquantes (non définies) dans le chemin, vous n'obtenez pas d'erreur, cela vous renvoie le troisième paramètre.
Pour le filtre de tableau, lodash a
_.find()
mais je préfère utiliser le régulierfilter()
. Mais je pense toujours que la méthode ci-dessus_.get()
est super utile lorsque vous travaillez avec des données vraiment complexes. J'étais confronté dans le passé à des API très complexes et c'était pratique!J'espère que cela peut être utile pour ceux qui recherchent des options pour manipuler des données vraiment complexes que le titre implique.
la source
Je ne pense pas que le questionneur concerne uniquement un objet imbriqué de niveau, je présente donc la démo suivante pour montrer comment accéder au nœud de l'objet json profondément imbriqué. Très bien, trouvons le nœud avec l'ID '5'.
la source
Vous pouvez utiliser la syntaxe
jsonObject.key
pour accéder à la valeur. Et si vous souhaitez accéder à une valeur à partir d'un tableau, vous pouvez utiliser la syntaxejsonObjectArray[index].key
.Voici les exemples de code pour accéder à différentes valeurs pour vous donner l'idée.
la source
Approche dynamique
Dans la
deep(data,key)
fonction ci-dessous , vous pouvez utiliser unekey
chaîne arbitraire - dans votre casitems[1].name
(vous pouvez utiliser la notation de tableau[i]
à n'importe quel niveau) - si la clé n'est pas valide, undefined est retourné.Afficher l'extrait de code
la source
Une approche pythonique, récursive et fonctionnelle pour démêler des arbres JSON arbitraires:
où data est une liste python (analysée à partir d'une chaîne de texte JSON):
la source
La fonction grep de jQuery vous permet de filtrer à travers un tableau:
la source
la source
En 2020, vous pouvez utiliser @ babel / plugin-proposition-optional-chaining, il est très facile d'accéder aux valeurs imbriquées dans un objet.
https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining
https://github.com/tc39/proposal-optional-chaining
la source
Mon
stringdata
vient d'un fichier PHP mais quand même, je l'indique icivar
. Quand je prends directement mon json,obj
cela ne montrera rien, c'est pourquoi je mets mon fichier json en tant quevar obj=JSON.parse(stringdata);
donc après que je reçoismessage
obj et que je montre dans la boîte d'alerte alors je reçoisdata
qui est le tableau json et le stocke dans une variableArrObj
puis je lis le premier objet de ce tableau avec une valeur clé comme celle-ciArrObj[0].id
la source
stringjson
ne s'agit pas d'une chaîne.Utiliser lodash serait une bonne solution
Ex:
la source