Traversant la chaîne JSON vers les niveaux internes à l'aide de la fonction récursive

J'ai une entrée JSON qui peut aller à n'importe quel nombre de niveaux.

Je donne un échantillon de

var d=getEntities( {"Categories": { "Facets": [ { "count": 1, "entity": "Company", "Company": [ { "entity": "Ford Motor Co", "Ford_Motor_Co": [ { "count": 1, "entity": "Ford" } ] } ] }, { "count": 4, "entity": "Country", "Country": [ { "entity": "Germany", "Germany": [ { "count": 1, "entity": "Germany" } ], "currency": "Euro (EUR)" }, { "entity": "Italy", "Italy": [ { "count": 1, "entity": "Italy" } ], "currency": "Euro (EUR)" }, { "entity": "Japan", "Japan": [ { "count": 1, "entity": "Japan" } ], "currency": "Yen (JPY)" }, { "entity": "South Korea", "South_Korea": [ { "count": 1, "entity": "South Korea" } ], "currency": "Won (KRW)" } ] }, {"count": 5, "entity": "Persons", "Persons": [ { "count": 2, "entity": "Dodge" }, { "count": 1, "entity": "Dodge Avenger" }, { "count": 1, "entity": "Major League" }, { "count": 1, "entity": "Sterling Heights" } ] } ] }}); 

Je souhaite ajouter la valeur de la clé "Entité" dans tous les niveaux à un tableau en utilisant la récursivité,

Je peux collecter les données du premier niveau à l'aide de la chaîne

 <html> <head> <script src="jquery.js" type="text/javascript"></script> <script type="text/javascript" src="dataDumper.js"></script> <script type="text/javascript"> var testJSON = {"Categories": { "Facets": [ { "count": 1, "entity": "Company", "Company": [ { "entity": "Ford Motor Co", "Ford_Motor_Co": [ { "count": 1, "entity": "Ford" } ] } ] }, { "count": 4, "entity": "Country", "Country": [ { "entity": "Germany", "Germany": [ { "count": 1, "entity": "Germany" } ], "currency": "Euro (EUR)" }, { "entity": "Italy", "Italy": [ { "count": 1, "entity": "Italy" } ], "currency": "Euro (EUR)" }, { "entity": "Japan", "Japan": [ { "count": 1, "entity": "Japan" } ], "currency": "Yen (JPY)" }, { "entity": "South Korea", "South_Korea": [ { "count": 1, "entity": "South Korea" } ], "currency": "Won (KRW)" } ] }, {"count": 5, "entity": "Persons", "Persons": [ { "count": 2, "entity": "Dodge" }, { "count": 1, "entity": "Dodge Avenger" }, { "count": 1, "entity": "Major League" }, { "count": 1, "entity": "Sterling Heights" } ] } ] }}; function scan(obj) { var k; if (obj.hasOwnProperty('entity')) { for (k in obj){ if (obj.hasOwnProperty(k)){ scan( obj[k] ); } } } else{ if(k=='entity') { alert(obj.entity); } } }; scan(testJSON); </script> </head> <body> </body> </html> 

Comment puis-je entrer dans les niveaux internes pour la chaîne JSON en utilisant des fonctions récursives?

J'ai fait un jsfiddle qui traverse chaque objet, tableau et valeur dans l'objet JS comme tel …

 function scan(obj) { var k; if (obj instanceof Object) { for (k in obj){ if (obj.hasOwnProperty(k)){ //recursive call to scan property scan( obj[k] ); } } } else { //not an Object so obj[k] here is a value }; }; 

Je n'obtiens aucune erreur de récurrence (dans Chrome). Pouvez-vous utiliser cela pour faire ce que vous voulez?

Si vous devez tester si un objet est un réseau, utilisez if (obj instanceof Array)

Pour vérifier si un objet a une propriété "entité", utilisez if (obj.hasOwnProperty('entity'))

Pour ajouter (ou modifier une propriété existante) "entité", utilisez obj.entity = value ou obj['entity'] = value

 (function recur( obj ) { Object.keys( obj ).forEach( function( prop ) { // Check if the property is an object if ( ({}).toString.apply( prop ) === '[object Object]' ) { // If it is, recall this function recur( prop ); } } ); } () ); 

Je n'ai pas ajouté votre logique, mais vous avez l'idée de parcourir de manière récursive votre objet.

Disons que j'ai une structure comme celle-ci:

 var aObject = { items: [], children: {} } 

Les enfants sont un tableau associatif qui contient plus d'objets. Donc, cela pourrait ressembler à ceci:

 var aObject = { items: [], children: { "subgroup1": { items: [], children: {} }, "subgroup2": { items: [], children: {} } } } 

J'ai un élément qui contient un éventail de sous-groupes:

 ["subgroup1", "subgroup1a"] 

Chaque sous-groupe est un «lieu». L'élément doit être placé à:

 aObject.children[array[0]].children[array[1]].items 

À chaque niveau, nous devons vérifier si les enfants [tableau [i]] existent, et sinon, créez-le. Vous ne pouvez pas simplement écrire aObject.children [array [0]]. Children [array [1]]. Items.push (item) car les enfants [array [0]] peuvent ne pas exister et nous obtiendrons une erreur.

Cela peut être résolu en utilisant la récurrence! (AngularJS)

 function recursive(aLevel, aItem, aArray, aIndex){ var lLevel = aLevel; // If we have reached the end of the array if (aIndex === aArray.length){ // Insert aLevel.items.push(aItem); } else { // If the subgroup doesn't exist, create it if (typeof aLevel.children[aArray[aIndex]] === 'undefined'){ aLevel.children[aArray[aIndex]] = { items: [], children: {} }; } // Move into recursive(aLevel.children[aArray[aIndex]], aItem, aArray, aIndex+1); } } aObject = { items: [], children: {}, } angular.forEach(items, function(item, i){ var location = item.location; if (location.length == 0){ aObject.items.push(item); } else { recursive(aObject, item, location, 0); } }); 

L'objet final ressemblerait à ceci:

 var aObject = { items: [], children: { "subgroup1": { items: [], children: { "subgroup1a": { items: [item], children: {} } } }, "subgroup2": { items: [], children: {} } } } 

Voici une fonction que j'utilise souvent. Il est facilement modifiable pour effectuer de nombreuses tâches récursives. Par exemple, si vous ajoutez un indicateur de caution, vous pouvez rapidement obtenir la pile ou ajouter une fonction de rappel qui la rend encore plus générale. De toute façon, c'est mes 2 cents

 var recursiveObjMap = (function(){ var stack = []; var result = []; // var bail = false; return function map(data, key){ if (!$.isArray(data) && !$.isPlainObject(data) ) { result.push(data); return false } $.each(data, function(i, v){ if (key) stack.push(key); map(v, i); stack.pop(); }); return result; }; })(); recursiveObjMap({a:'b',c:{d:{e:"f"}}}) // ['b', 'f']