使用递归函数遍历 JSON 字符串到内部级别

IT技术 javascript arrays json object
2021-02-24 13:33:14

我有一个可以进入任意级别的 JSON 输入。

我正在给出一个输入样本

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

}});

我想使用递归将所有级别的键值“实体”​​添加到数组中,

我可以使用字符串从第一级收集数据

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

如何使用递归函数进入 JSON 字符串的内部级别?

5个回答

我制作了一个jsfiddle,它遍历 JS 对象中的每个对象、数组和值,就像这样......

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 {
        //obj is not an instance of Object so obj here is a value
    };

};

我没有得到递归错误(在 Chrome 中)。你能用它来做你想做的事吗?

如果您需要测试对象是否是数组,请使用 if (obj instanceof Array)

要测试对象是否具有“实体”属性,请使用 if (obj.hasOwnProperty('entity'))

添加(或修改现有)“实体”属性使用obj.entity = valueobj['entity'] = value

“停止表达”是我在回答中使用的表达:if ( ({}).toString.apply( prop ) === '[object Object]' ) {. 顺便说一句,Object.keys返回可枚举属性的数组,因此不需要使用hasOwnProperty.
2021-04-29 13:33:14
啊,您可能不熟悉在进入循环之前测试 'if (h instanceof object)'。
2021-05-01 13:33:14
它显示错误,如果没有为 If (h.hasOwnProperty(k)) 定义
2021-05-08 13:33:14
我已经在我的 iPhone 上回答了这个问题,所以如果有人可以修复我的格式,我将不胜感激!!!
2021-05-09 13:33:14
不,,,它是你代码的格式......我是大写字母......它现在提醒第一个实体公司,然后为 getEntities(h[k]); 显示“太多递归”;
2021-05-19 13:33:14
(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 );
        }
    } );
} () );

我没有添加你的逻辑,但你知道如何递归遍历你的对象。

什么?我不明白你的评论。
2021-04-26 13:33:14
还有一个疑问,对于这个疑问的递归。如果我想获得福特汽车公司的value,我可以这样做 h.Categories.Facets[0].Company[0].entity 或者我使用 h.Categories.Facets[0].entity 获得value Company然后我如何将值 Company 附加到“h.Categories.Facets[[0].'()'.entity”行..
2021-05-01 13:33:14
糟糕,正确编辑了我的答案。subobj是,对象的属性一个对象,这样你就可以穿越它。
2021-05-14 13:33:14
我不确定我找到了你,但你在寻找:h.Categories.Facets[[0]. '()' .entity = h.Categories.Facets[0].Company[0].entity第一部分显然不好,但我不明白你的意思。
2021-05-14 13:33:14
我如何在上面的例子中添加 subobj 的值?
2021-05-17 13:33:14

假设我有如下结构:

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

Children 是一个包含更多 aObject 的关联数组。所以它看起来像这样:

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

我有一个包含子组数组的项目:

["subgroup1", "subgroup1a"]

每个子组都是一个“位置”。该物品需要放置在:

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

在每个级别,我们必须检查 children[array[i]] 是否存在,如果不存在,则创建它。你不能简单地写 aObject.children[array[0]].children[array[1]].items.push(item) 因为 children[array[0]] 可能不存在,我们会得到一个错误。

这可以使用递归解决!(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);
    }
});

最终的 aObject 将如下所示:

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

这是我经常使用的功能。很容易修改以执行许多递归任务。例如,如果您添加一个保释标志,您可以快速获取堆栈或添加一个回调函数,使其更加通用。无论如何,这是我的 2 美分

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']
const obj = [
  {
    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 test(runObj) {
  for (let i in runObj) {
    typeof runObj[i] == "object" ? test(runObj[i]) : console.log(runObj[i]);
  }
}
test(obj);