【问题标题】:Recursive JSON object display with different child name具有不同子名称的递归 JSON 对象显示
【发布时间】:2016-07-21 01:44:23
【问题描述】:

我目前正在学习 AngularJS,我正在尝试实现一个 JSON 复杂对象显示器。我在this question 甚至here 中阅读了很多关于此类问题的内容,并且有一些回应元素,但这些对我的情况并没有太大帮助。

前面提到的主题向我展示了当孩子总是使用相同的名字时的一些很好的解决方案(例如,孩子元素总是被称为“孩子”,例如1)。但是我们如何处理不同的名字呢?我搜索了一种方法来获取子对象而不管它的名称,但没有找到。

我的 JSON 对象如下所示:

{
  name: "Something",
  _id: "some ID",
  Firstchildren: [
       {
        name: "Children1"
        type: "Child"
        SecondChildren: [
          {
             name: "ChildrenOfDoom",
             type: "Doom"
             ThirdChildren: [
                {
                 name: "BoredOne",
                 type: "Bored
                },
                {
                 name: "AnotherOne",
                 type: "Boring"
                }
             ]
          },
       <another SecondChildren>
    ]}

基本上我的问题如下:有没有办法递归地处理复杂的 JSON 对象而不管孩子的名字是什么?因此,在我们的示例中,最终显示如下:

Something
     Child1 : Child
          ChildrenOfDoom : Doom
              BoredOne : Bored
              AnotherOne : Boring
          ChildrenOfChaos : Chaotic
              SomeOne : Random
              ...
          ...
     Child2 : Child
          ...

当然,如果有这样的方法,我想了解一下,无论是完整的解决方案、建议、文档还是有用的教程。

提前谢谢你!

PS:如果可能,请避免“可能重复”,如果它们已经在原始问题中链接,我已经完成了。 PPS:尽管有上述第一个问题,但我也不会回答其他相关问题,只要它们尚未在此处引用即可。

【问题讨论】:

    标签: javascript angularjs json recursion


    【解决方案1】:

    此函数返回给定对象包含“子”的任何属性的名称

    function getChildrenProperty(object) {
      for (var property in object) {
        if (object.hasOwnProperty(property)) {
          if (property.toLowerCase().indexOf("children") > -1) {
            return property;
          }
        }
      }
    
      return null;
    }
    

    然后在你的递归函数中,你可以像这样使用它

    var childrenProperty = getChildrenProperty(object);
    if (childrenProperty !== null) {
      recursiveFunction(object[childrenProperty]);
    }
    

    [EDIT]如果您想检查多种儿童(例如,您在结构中引入 Brothers、Sisters 或 Cowboy Beepops),您可以乘以您的研究术语:

    function getChildrenProperty(object) {
      for (var property in object) {
        if (object.hasOwnProperty(property)) {
          if (property.toLowerCase().indexOf("children") > -1) {
            return property;
          }
          // You also search for cowboys here
          if (property.toLowerCase().indexOf("cowboys") > -1) {
            return property;
          }
          // And for demons, because you need it
          if (property.toLowerCase().indexOf("demons") > -1) {
            return property;
          }
         // As much as you want, you should use a function
         // if you need a lot of cases to check ;)
        }
      }
    
      return null;
    }
    

    还要确保您需要那些“小写字母”,因为它可能会给您带来一些问题。我刚刚遇到了一个问题,我的属性类似于“halfWay”,而下面提供的这段代码 sn-p 找不到该属性,因为它正在将其转换为“halfway”。否则,它工作得非常顺利。

    var app = angular.module("app", []);
    
    app.controller("controller", function($scope) {
      $scope.object = {
        name: "Something",
        _id: "some ID",
        FirstChildren: [{
          name: "Child1",
          type: "Child",
          SecondChildren: [{
            name: "ChildrenOfDoom",
            type: "Doom",
            ThirdChildren: [{
              name: "BoredOne",
              type: "Bored"
            }, {
              name: "AnotherOne",
              type: "Boring"
            }]
          }]
        }, {
          name: "Child2",
          type: "Child",
          SecondChildren: [{
            name: "Child of Child2",
            type: "Space Cowboy"
          }]
        }]
      };
    
      var str = ""; // The string we'll be creating. We'll add it to scope once everything is done
    
      // Recursive function, this will keep calling itself if the object has children
      // The `level` parameter is used to determine how many tabs to adds to the start of each line
      function addObjectsToString(objects, level) {
        // We want an array of objects to iterate over and add to the string. So if it isn't an array, make a new array containing only `objects` which is actually a single object
        if (!Array.isArray(objects)) {
          objects = [objects];
        }
    
        for (var i = 0; i < objects.length; i++) {
          var object = objects[i];
    
          // Add indentation
          for (var j = 0; j < level; j++) {
            str += "    "; // 4 spaces because tab seemed a bit much
          }
    
          // Add the object name, presumably all objects will have a name
          str += object.name;
    
          // If the object has a type add " : type"
          if (angular.isDefined(object.type)) {
            str += " : " + object.type;
          }
    
          // Add a new line
          str += "\n";
    
          // If the object has a children property, call this function with reference to the object's children
          var childrenProperty = getChildrenProperty(object);
          if (childrenProperty !== null) {
            addObjectsToString(object[childrenProperty], level + 1);
          }
        }
      }
    
      // Returns the name of any property containing "children"
      function getChildrenProperty(object) {
        for (var property in object) {
          if (object.hasOwnProperty(property)) {
            if (property.toLowerCase().indexOf("children") > -1) {
              return property;
            }
          }
        }
    
        return null;
      }
    
      // Very first call to the recursive function
      addObjectsToString($scope.object, 0);
    
      // Add the string to the scope so we can display it on the page
      $scope.result = str;
    });
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
    <div ng-app="app" ng-controller="controller">
      <pre>{{result}}</pre>
    </div>

    【讨论】:

    • 这帮助我解决了这个问题,并且足够高效和清晰。谢谢 ! PS:小心,如果您想检查名称中不包含“孩子”的对象,则必须包括其他检查器:p。
    猜你喜欢
    • 1970-01-01
    • 2014-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多