javascript - 递归扩展json对象

标签 javascript jquery json recursion

我有一个递归 json 结构,其中包含一些属性和一个包含子节点的节点,其格式与所需的深度相同。下面的示例不完整或与我的数据相同,但它显示了粗略的结构。

[{"page":{
    title: "my title 1",
    children: [
        {"page":{
            title: "my title 2",
            children: [ ... ]
        },{"page":{
            title: "my title 3",
            children: [ ... ]
        },{"page":{
            title: "my title 4",
            children: [
                {"page": {
                    title: "my other title",
                    children: [ ... ]
                }]
        },{"page":{
            title: "my title 5",
            children: [ ... ]
        }]
        ... etc

我想扩展该对象,以便每个“页面”对象都获得一组新的属性 - 例如假设我想将 {score: 5.3, theme:"moody"} 添加到每个“页面”,以便它们都获得属性,这样如果我要对 json 对象进行字符串化,每个页面都会然后添加这些属性。

{"page":{title:"some title", score: 5.3, theme: "moody"}}

有没有办法递归扩展 json/对象结构,最好是在 jQuery 中?

最佳答案

首先,您拥有的是一个对象数组。数组是原生 JS 对象(实际上是 Object 的增强实例)。 JS 中不存在JSON 对象,因为 JSON 是 JavaScript Object Notation 的缩写。
它是一种经常用于传输数据的格式,但格式良好的 JSON 是格式良好的 JS 文字表示法。如此之多以至于您可以eval 一个 JSON 字符串,但是无论您做什么,都不要More details can be found here

尽管如此,你得到的任何解决方案都将是 JavaScript 解决方案,因为 jQ 就是 JavaScript...你在 JS 中所做的一切都在 jQ 中工作,你编写的每条涉及 jQ 的语句都会评估一系列函数调用和构成 jQ 工具包的其他魔法,所有这些都是用普通的 'ol VanillaJS 编写的。

然而,回到你的问题。看看你的结构,我想我说每个 children 属性都是一个数组,包含对象,(可能)有一个 page 属性。该属性将有一个对象分配给它。这些都是我的假设,但我的印象是这里就是这种情况。这意味着,要扩展这个对象,一个简单的映射回调函数就足够了:

yourArray = yourArray.map(function ext(obj)
{//named callback function, does not pollute global scope
   obj.title = "title";
   obj.score = 5.3;
   if (obj.children instanceOf Array)
   {//recursively apply callback
       obj.children = obj.children.map(ext);//reference to current callback function
   }
   return obj;//return altered object
});

这会映射每个数组,为对象分配属性,然后检查是否有 children 属性,这也是一个数组,并应用相同的回调函数来映射该数组,从而渲染这个映射是递归的。
因为我们在这里处理对象,所以 return obj 语句实际上是可选的,因为对象是引用:

yourArray.map(function ext(obj)
{//no assignment
   obj.title = "title";
   obj.score = 5.3;
   if (obj.children instanceOf Array)
   {
       obj.children = obj.children.map(ext);
   }
});

同样有效
使用 jQuery 的 extend 方法,您可以稍微缩短这段代码,但不会缩短很多(实际上是 1 行),当然:

yourArray = yourArray.map(function ext(obj)
{
   $.extend(obj, {title: 'title',score: 5.3});
   if (obj.children instanceOf Array)
   {
       obj.children = obj.children.map(ext);
   }
   return obj;
});

或者,更像 jQ 风格:

$.each(yourArray, function ext(i, obj)
{
    $.extend(obj, {title: 'title', score: 5.3});
    if (obj.children instanceof Array)
    {
        $.each(obj.children(ext));
    }
});

但是正如您所见,就可读性和代码紧凑性而言,差异相当小。 jQ 在这里所做的一切,真的,就是让你慢下来,老实说。
因为 $.extend 需要一个对象作为第二个参数,所以我必须在每次回调调用时构造一个对象文字。我不能使用分配给驻留在更高范围内的变量的对象,因为如前所述:永远不会复制对象,只有对它们的引用。使用来自更高范围的变量会使代码更容易出错:

var extendObj = {title: 'title', score: 4};
yourArray = yourArray.map(function ext(obj)
{
   $.extend(obj, extendObj);
   if (obj.children instanceOf Array)
   {
       obj.children = obj.children.map(ext);
   }
   return obj;
});

这会很完美,但是:

var extendObj = {title: 'title', score: 4, deep:{another: 'object'}};

需要深度克隆:

$.extend(true, obj, extendObj);

如果您忘记/忽略这一点,通过一个实例更改 deep 的属性,将意味着所有其他实例也反射(reflect)相同的更改......不理想

关于javascript - 递归扩展json对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20069933/

相关文章:

javascript - Jquery对话框错误: cannot call methods on dialog prior to initialization; attempted to call method 'close'

javascript - 在更改输入文本时在文本区域中插入数据

json - 如何在电子表格中定义标题以从 Google 电子表格 API 获取 JSON 响应中的 gsx$title 属性?

javascript - React 菜鸟在将组件导出到另一个组件时遇到问题

javascript - 如何在 Bootstrap 模式关闭时停止 HTML 视频?

javascript - 如何在 perl CGI 中获取访问者浏览器窗口大小

javascript - 使用 Rangy Library 在 contentEditable div 中获取准确的插入符位置

jquery - 如何从特定表单中删除字段

c# - 在 UWP 的 gridview 中检索 JSON 数据

json - go 中的 JSON panic