我认为这一定是一个常见的问题,但似乎无法找到解决方案。 使用JSON配置文件扩展包含对象和数组的jQuery对象。
对于对象和简单属性,我想覆盖(因为extend
很好)。
对于阵列,可能存在也可能不存在现有项目。
目前,数组只会覆盖第一个元素
var sourceObj = {propterty:"change Me",anArray:[{name:"first"},{name:"second"}]},
configJSON = '{"propterty":"New Val","anArray":[{"name":"third"}]}',
configObj = JSON.parse(configJSON);
$.extend(true,sourceObj,configObj);
返回:
{propterty:"New Val" , anArray:[{name:"third"},{name:"second"}}
我可以改为:
{propterty:"New Val",anArray:[{name:"first"},{name:"second"},{name:"third"}]}
虽然ALSO允许更新“第一”和“第二”对象?
"anArray":[{"name":"second","newProp":"add newProp to second"}]
可以/应该extend
修改以比较数组项,并根据某些规则或设置属性值(例如“name”)进行扩展或添加吗?
感谢您的任何建议或指示。
答案 0 :(得分:2)
我使用了此解决方案http://jsfiddle.net/PmuwV/2/ 已从How can I merge properties of two JavaScript objects dynamically?
修改JavaScript equivalent of jQuery's extend method需要isDOMNode() 我刚刚在数组中添加了一个jquery合并(是的,我也觉得很脏),其中需要在合并后清理重复项。 扩展的Jquery源代码非常相似,但我发现它更具可读性。
function mergeRecursive() {
// _mergeRecursive does the actual job with two arguments.
var _mergeRecursive = function (dst, src) {
if ( isDOMNode(src) || typeof src!=='object' || src===null) {
return dst;
}
for ( var p in src ) {
//my added bit here - [SB]
if ($.isArray(src[p])){
$.merge(dst[p],src[p]);
var dupes = {},
singles = [];
$.each( dst[p], function(i, el) {
if ((dupes[el.name] > -1) && (el.name)) {
$.extend(singles[dupes[el.name]],el);
}else{
if (el.name ){
dupes[el.name] = i;
}
singles.push(el);
}
});
dst[p] = singles;
}
continue;
}
//the rest is original - [SB]
if( !src.hasOwnProperty(p) ) continue;
if ( src[p]===undefined ) continue;
if ( typeof src[p]!=='object' || src[p]===null) {
dst[p] = src[p];
} else if ( typeof dst[p]!=='object' || dst[p]===null ) {
dst[p] = _mergeRecursive(src[p].constructor===Array ? [] : {}, src[p]);
} else {
_mergeRecursive(dst[p], src[p]);
}
}
return dst;
}
// Loop through arguments and merge them into the first argument.
var out = arguments[0];
if ( typeof out!=='object' || out===null) return out;
for ( var i=1, il=arguments.length; i<il; i++ ) {
_mergeRecursive(out, arguments[i]);
}
return out;
}
答案 1 :(得分:2)
true/false
结果是:
var targetObj = {
customerId: "123",
orders: [
"item1", "item2"
]
};
var otherObj = {
customerName: "John",
orders: [
"item3", "item4"
]
};
_.merge(targetObj, otherObj, function (a, b) {
if (_.isArray(a)) {
return a.concat(b);
}
});
答案 2 :(得分:0)
我知道这已经过时了,但我发现这篇帖子并使用了上面的Steve Blacks代码,但发现了一些错误:
如果源根本没有数组,它会抛出一个 错误,所以我将其添加到isArray部分
if ( !dst[p] ) {
dst[p] = src[p];
continue;
}
所以完成的代码如下所示:
function isDOMNode(v) {
if ( v===null ) return false;
if ( typeof v!=='object' ) return false;
if ( !('nodeName' in v) ) return false;
var nn = v.nodeName;
try {
v.nodeName = 'is readonly?';
} catch (e) {
return true;
}
if ( v.nodeName===nn ) return true;
v.nodeName = nn;
return false;
}
function mergeRecursive() {
// _mergeRecursive does the actual job with two arguments.
var _mergeRecursive = function (dst, src) {
if ( isDOMNode(src) || typeof src!=='object' || src===null) {
return dst;
}
for ( var p in src ) {
if ($.isArray(src[p])) {
if ( !dst[p] ) {
dst[p] = src[p];
continue;
}
$.merge(dst[p],src[p]);
var dupes = {}, singles = [];
$.each( dst[p], function(i, el) {
if ((dupes[el.name] > -1) && (el.name)) {
$.extend(singles[dupes[el.name]],el);
} else {
if (el.name) {
dupes[el.name] = i;
}
singles.push(el);
}
});
dst[p] = singles;
continue;
}
if ( !src.hasOwnProperty(p) ) continue;
if ( src[p]===undefined ) continue;
if ( typeof src[p]!=='object' || src[p]===null) {
dst[p] = src[p];
} else if ( typeof dst[p]!=='object' || dst[p]===null ) {
dst[p] = _mergeRecursive(src[p].constructor===Array ? [] : {}, src[p]);
} else {
_mergeRecursive(dst[p], src[p]);
}
}
return dst;
}
// Loop through arguments and merge them into the first argument.
var out = arguments[0];
if ( typeof out!=='object' || out===null) return out;
for ( var i=1, il=arguments.length; i<il; i++ ) {
_mergeRecursive(out, arguments[i]);
}
return out;
}
答案 3 :(得分:0)
<html>
<head>
<script type="text/javascript" src="./jquery-2.1.3.js"></script> <!-- for json extend / merge -->
<script type="text/javascript" src="./jQuery.extendext.min.js"></script> <!-- for json extend / merge - with array extend (instead of array overwrite) - https://github.com/mistic100/jQuery.extendext -->
<script>
var jsonResult = {};
var json1 =
{
"properties":
{
"street_address": { "type": "string" },
"city": { "type": "string" },
"state": { "type": "string" }
},
"required": ["street_address", "city", "state"]
};
var json2 =
{
"properties":
{
"country": { "type": "string" },
"country-dial-code": { "type": "integer" },
"country-short": { "type": "string" }
},
"required": ["country", "country-dial-code", "country-short"]
};
$.extendext(true, 'extend', jsonResult, json1, json2);
console.log(JSON.stringify(jsonResult));
/* output ->
{ "properties":
{ "street_address":{"type":"string"},
"city":{"type":"string"},
"state":{"type":"string"},
"country":{"type":"string"},
"country-dial-code":{"type":"integer"},
"country-short":{"type":"string"}
},
"required":["street_address","city","state","country","country-dial-code","country-short"]
}
*/
</script>
</head>
<body>
</body>
</html>