javascript - 具有不同子名称的递归 JSON 对象显示

标签 javascript angularjs json recursion

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

前面提到的主题向我展示了当子元素始终具有相同名称时的一些好的解决方案(例如,子元素始终称为“Children”,例如 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 对象,而不管 child 的名字是什么?因此,在我们的示例中,最终显示如下:

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

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

提前谢谢您!

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

最佳答案

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

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]);
}

[编辑]如果您想检查多种类型的 child (例如,您在结构中引入了兄弟、姐妹或牛仔蜂鸣),您可以乘以您的研究术语:

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”,下面提供的代码片段找不到该属性,因为它将其转换为“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>

关于javascript - 具有不同子名称的递归 JSON 对象显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36353148/

相关文章:

javascript - 如何在 Javascript 中检查函数的返回值是否未定义

javascript - 多次触发 Google+ oauth2 回调

javascript - Model.function 不是路由器内的函数

angularjs - 使用酱汁和 Protractor 测试 Internet Explorer 和 Safari

javascript - ng-click Angular Directive(指令)

javascript - 如何将 javascript 结果保存到 gulp 中的文件中

json - Golang解析为struct

javascript - 运行 Babel 转译代码时需要 JSON 文件会引发 Node.js 加载程序错误 "Error: Cannot find module ' example.json'"

javascript - 如何将复合数组从 Javascript 传递到 WEB API Controller HttpPOST?

json - Web 服务架构中 MVC 设计模式的实现是否应该由多个组件组成?