Javascript 递归扩展json对象
我有一个递归json结构,其中包含一些属性和一个包含子节点的节点,其格式与需要的深度相同。下面的示例并不完整,也与我的数据不同,但它显示了大致的结构Javascript 递归扩展json对象,javascript,jquery,json,recursion,Javascript,Jquery,Json,Recursion,我有一个递归json结构,其中包含一些属性和一个包含子节点的节点,其格式与需要的深度相同。下面的示例并不完整,也与我的数据不同,但它显示了大致的结构 [{"page":{ title: "my title 1", children: [ {"page":{ title: "my title 2", children: [ ... ] },{"page":{ title: "my
[{"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对象(实际上是
对象
的一个扩展实例)。JS中没有JSON对象,因为JSON是JavaScript对象表示法的首字母缩写。这是一种通常用于传输数据的格式,但格式良好的JSON是格式良好的JS文字符号。如此之多以至于您可以
eval
一个JSON字符串,但是无论您做什么,都不要
尽管如此,您得到的任何解决方案都将是JavaScript解决方案,因为jQ就是JavaScript。。。您在JS中所做的一切都在jQ中工作,您编写的每一条涉及jQ的语句都会计算为一系列函数调用和构成jQ工具包的其他魔法,所有这些都是用普通的“ol VanillaJS”编写的
然而,回到你的问题上来。看看你的结构,我想我说得对,每个子属性
都是一个数组,包含对象,可能有一个页面
属性。此属性将指定一个对象。这些都是我的假设,但我的印象是,这里就是这样。这意味着,要扩展此对象,一个简单的映射回调函数就足够了:
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
});
这将映射每个数组,将属性分配给对象,然后检查是否有子属性,这也是一个数组,并应用相同的回调函数映射该数组,从而使此映射成为递归映射。
因为我们在这里处理对象,returnobj
语句实际上是可选的,因为对象是引用:
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
方法,您可以稍微缩短这段代码,但不会缩短太多(实际上是一行),当然:
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;
});
这将非常有效,但是:
需要深度克隆:
$.extend(true, obj, extendObj);
如果您忘记/忽略这一点,通过一个实例更改deep
的属性,则意味着所有其他实例也反映了相同的更改。。。不理想首先,您拥有的是一个对象数组。数组是一个原生JS对象(实际上是对象
的一个扩展实例)。JS中没有JSON对象,因为JSON是JavaScript对象表示法的首字母缩写。
这是一种通常用于传输数据的格式,但格式良好的JSON是格式良好的JS文字符号。如此之多以至于您可以eval
一个JSON字符串,但是无论您做什么,都不要
尽管如此,您得到的任何解决方案都将是JavaScript解决方案,因为jQ就是JavaScript。。。您在JS中所做的一切都在jQ中工作,您编写的每一条涉及jQ的语句都会计算为一系列函数调用和构成jQ工具包的其他魔法,所有这些都是用普通的“ol VanillaJS”编写的
然而,回到你的问题上来。看看你的结构,我想我说得对,每个子属性
都是一个数组,包含对象,可能有一个页面
属性。此属性将指定一个对象。这些都是我的假设,但我的印象是,这里就是这样。这意味着,要扩展此对象,一个简单的映射回调函数就足够了:
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
});
这将映射每个数组,将属性分配给对象,然后检查是否有子属性,这也是一个数组,并应用相同的回调函数映射该数组,从而使此映射成为递归映射。
因为我们在这里处理对象,returnobj
语句实际上是可选的,因为对象是引用:
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
方法,您可以稍微缩短这段代码,但不会缩短太多(实际上是一行),当然:
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;
});
这将非常有效,但是:
需要深度克隆:
$.extend(true, obj, extendObj);
如果您忘记/忽略这一点,通过一个实例更改deep
的属性,则意味着所有其他实例也反映了相同的更改。。。不理想创建一个fiddl