我有基于 XML 文件生成的表单输入。
我们通过 data-*
在 XML 文件中保留嵌套元素的引用稍后可用于构建对象的属性。例如:
<parent>
<child>
<grandchild1>first</grandchild1>
<grandchild2>second</grandchild2>
</child>
</parent>
成为
<input type="text" data-nest="parent.child.grandchild1" value="first"/>
<input type="text" data-nest="parent.child.grandchild2" value="second"/>
当我们提交表单时,我根据他们的 data-nest
创建了一个对象(带有嵌套对象)属性。上面会变成
parent:{
child:{
grandchild1: first,
grandchild2: second
}
}
我遇到的问题是在 XML 文件中发现了多个相同的标签,例如
<child>
<grandchild>first</grandchild>
<grandchildFriend>firstFriend</grandchildFriend>
</child>
<child>
<grandchild>second</grandchild>
<grandchildFriend>secondFriend</grandchildFriend>
</child>
当我创建我的对象时,我希望它能使相同的 data-nest
多次出现。找到值后,它们嵌套在一个数组中以维护不同的值。
在当前设置下,第二次出现的标记会覆盖第一次出现,这是可以理解的。
这是我想要的最终对象结构:
parent:{
child:[
{
grandchild: first,
grandchildFriend: firstFriend
},
{
grandchild: second,
grandchildFriend: secondFriend
}
]
}
长话短说
我想将一个对象更改为嵌套对象数组,如果它们具有相同的 data-*
。属性
这是一个 fiddle当前代码的工作原理有助于更好地理解。
最佳答案
将 currentObj[lastKey] = value;
替换为:
if(typeof currentObj[lastKey] === 'undefined') {
currentObj[lastKey] = value;
} else {
if(typeof currentObj[lastKey] !== 'array')
currentObj[lastKey] = [currentObj[lastKey]];
currentObj[lastKey].push(value);
}
代码将执行以下操作:如果未设置 currentObj[lastKey],您将一如既往地创建一个元素,否则,如果它已经设置并且是一个字符串,代码会将其转换为数组,然后插入数组 后续(任意数量)元素 最终结果将类似于:
parent:{
...
grandchild:[
"first", "second"
]
...
}
编辑 为了得到您要求的格式的结果,您需要做一些更多的编辑,如下所示:
var json = {};
config = {
set: function(keyValueString) {
var pair = keyValueString.split('=');
// left of the = is the key path
var keyPath = pair[0];
// right of the = is the value to set
var value = pair[1];
// split keyPath into an array of keys
var keys = keyPath.split('.');
var key;
var currentObj = json;
// loop through all keys in the key path, except the last one.
// this creates the object structure implied by the key path.
// we want to do something different on the last iteration.
for (var i=0; i < keys.length-1; i++) {
// Get the current key we are looping
key = keys[i];
// if the requested level on the current object doesn't exist,
// make a blank object.
if (typeof currentObj[key] === 'undefined') {
currentObj[key] = i === keys.length-2 ? []: {};
}
currentObj = currentObj[key];
}
// our loop doesn't handle the last key, because that's when we
// want to set the actual value.
var lastKey = keys[keys.length-1]
// set the property of the deepest object to the value.
var child = {};
child[lastKey] = value;
currentObj.push(child);
}
};
// iterate through all of our inputs, and nest them based off their data-* attribute
$('input').each(function(){
// set nest = value setup, e.g. parent.child.grandchild = first
// we then break this
var key = $(this).attr('data-nest') + '=' + $(this).val();
config.set(key);
});
// as a bonus - this is how I went about breaking multiple values within a single input into an array
function traverseObject(object){
// iterate through the object
for (var i in object){
// if the next key exists, run again
if(object[i] !== null && typeof(object[i])=="object"){
traverseObject(object[i]);
} else {
var value = [object[i]];
// if the value contains a comma
if(value.toString().indexOf(',') > -1){
// set the *nested* key to the
// value as an array by splitting at the commas
object[i] =value.toString().split(',').filter(function(el){
// remove the extra entry after splitting
return el.length != 0;
});
}
}
}
}
traverseObject(json);
$('#test').on('click', function(){
console.log(json)
});
关于javascript - 根据相同的属性名称创建对象数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47328345/