javascript - 如何创建反映嵌套 HTML 表单的嵌套 JSON 对象?
问题描述
我有一个与此类似的 HTML 表单(请注意,它是由选项卡、可选字段集和字段元素组织的):
- div.tab1
- div.fieldset3
- div.container308
- div.container314
- div.fieldset4
- div.container309
- div.container310
- div.fieldset3
- div.tab2
- div.fieldset1
- div.container311
- div.fieldset2
- div.container313
- div.container312
- div.fieldset1
- div.tab3
- div.container315
- div.container316
每个div
都是一个或多个input
元素的容器,但对于这个问题,我将重点放在容器上。
我正在尝试编写一个 JavaScript 函数,该函数将“遍历”指定的 HTML 元素并以这种格式生成 JSON 对象(注意基于表单的选项卡、字段集和输入元素形成的嵌套):
{
"content":
[
{
"type": "tab",
"id": "left-defaults1",
"order": 1,
"content":
[
{
"id": "fieldset-3",
"order": 1,
"type": "fieldset",
"content": [
{
"id": "container308",
"order": 1,
"type": "field"
},
{
"id": "container314",
"order": 1,
"type": "field"
},
{
"id": "fieldset-4",
"order": 1,
"type": "fieldset",
"content": [
{
"id": "container309",
"order": 1,
"type": "field"
},
{
"id": "container310",
"order": 1,
"type": "field"
}
]
}
]
},
]
},
{
"type": "tab",
"id": "left-defaults2",
"order": 2,
"content":
[
{
"id": "fieldset-1",
"order": 1,
"type": "fieldset",
"content": [
{
"id": "container311",
"order": 1,
"type": "field"
},
{
"id": "fieldset-2",
"order": 1,
"type": "fieldset",
"content": [
{
"id": "container313",
"order": 1,
"type": "field"
},
{
"id": "container312",
"order": 1,
"type": "field"
}
]
}
]
}
]
},
{
"type": "tab",
"id": "left-defaults3",
"order": 3,
"content":
[
{
"id": "container315",
"order": 1,
"type": "field"
},
{
"id": "container316",
"order": 1,
"type": "field"
}
]
}
]
}
我在通过第二个“层”时遇到了问题。我可以识别要“行走”的 HTML 元素,并且可以在 JSON 对象中建立“标签”级别。我还可以将下一层字段集或字段元素推入其中。但除此之外,我迷失了方向;我不知道如何在 JSON 对象中定位给定第三层的父级(或第四层或第五层等)。
这个 JavaScript 是该尝试的核心:
var createNestedJSON = function(){
//establish JSON object
var tab_order = 0,
form_content_nested_and_ordered = {'content': []},
element_ii_object = {};
//so we can retrieve them in the order they exist in the page, class as "JSONMe" all the things we are going to want to represent in form_content_nested_and_ordered
$('#fmWkflw').find('.tab-option-container').addClass('JSONMe').find('li').addClass('JSONMe');
$('.JSONMe').each(function(element_index){
var $this = $(this).data('JSON_id', element_index);
console.log('tag:'+ this.tagName +', id:'+ this.id +', parentId: '+ $this.parent().prop('id') +', className: '+ this.className);
if( this.tagName === 'UL' ){
//this is a tab; add it
form_content_nested_and_ordered["content"].push( {'type': 'tab', 'id': this.id, 'order': ++tab_order, 'content' : []} );
console.log('added tab');
}
else {
element_ii_object = {
'id': this.id,
'order': 1,
'type': 'field'
};
if( $this.hasClass('fieldset') ) {
//this is a fieldset, so it has type "fieldset" and a "content" array
element_ii_object.type = 'fieldset';
element_ii_object.content = [];
}
console.log(element_ii_object);
form_content_nested_and_ordered.content[ tab_order-1 ]['content'].push( element_ii_object );
console.log('added '+ element_ii_object.type);
};
});
/*
form_content_nested_and_ordered["content"][getIndexIfObjWithOwnAttr(form_content_nested_and_ordered["content"], 'id', 2)]['content'].push( {'type': 'field', 'id': 14, 'order': 12} );
form_content_nested_and_ordered["content"][getIndexIfObjWithOwnAttr(form_content_nested_and_ordered["content"], 'id', 1)]['content'].push( {'type': 'field', 'id': 23, 'order': 7} );
form_content_nested_and_ordered["content"][getIndexIfObjWithOwnAttr(form_content_nested_and_ordered["content"], 'id', 1)]['content'].push( {'type': 'field', 'id': 24, 'order': 8} );
*/
//tear down
$('#fmWkflw').find('.JSONMe').data('JSON_id', 0).removeClass('.JSONMe');
return form_content_nested_and_ordered;
};
解决方案
您好据我了解,您必须在那里进行递归,因为您不知道它的级别,所以这里有一个示例,希望对您有所帮助。
function copyTree(originalTree){
return originalTree.map((elem, index) => ({
id: 'div.'+elem.id,
content: !elem.content ? [] : this.copyTree(elem.content),
}));
}
编辑:
我误解了你想要的东西,这是你期望得到的东西,我希望这可以帮助你。
对代码的一些解释:我使用 querySelectorAll 是因为它返回一个可以迭代的 NodeList,[...arr] 的原因是
如果对象是可迭代的,它将从对象中创建一个数组。有关更多示例,请转到过滤器或映射 NodeList
之后我要做的是创建一个递归调用的函数,以便推送内容直到找不到更多匹配项。
var getIndexIfObjWithOwnAttr = function(array, attr, value) {
for(var i = 0; i < array.length; i++) {
if(array[i].hasOwnProperty(attr) && array[i][attr] === value) {
return i;
}
}
return -1;
};
var createNestedJSON = function(){
//establish JSON object
var tab_order = 0,
form_content_nested_and_ordered = {'content': []},
element_ii_object = {};
//so we can retrieve them in the order they exist in the page, class as "JSONMe" all the things we are going to want to represent in form_content_nested_and_ordered
$('#fmWkflw').find('.tab-option-container').addClass('JSONMe').find('li').addClass('JSONMe')
var htmltest = document.querySelectorAll('.JSONMe')
form_content_nested_and_ordered = function (arr){
return [...arr].map((elem, index) => ({
type: elem.localName,
id: elem.id,
content: elem.children && elem.children.length>0 && (elem.localName ==='li' || elem.localName ==='ul' || elem.localName ==='fieldset') ? form_content_nested_and_ordered(elem.children) : [],
}));
}
//console.log(form_content_nested_and_ordered(htmltest))
var filtered = form_content_nested_and_ordered(htmltest).filter((x)=>{
return x.type == 'ul'
})
return filtered;
};
$('#formSubmit').click(function(){
$('#resulting_JSON')[0].innerHTML = JSON.stringify(createNestedJSON());
});
推荐阅读
- c++ - c++中字符串向量的索引
- android - DeepLinking React Native App 与 firebase deeplink
- cluster-computing - 有什么方法可以知道 qsub 中接下来会开始哪个工作
- python-3.x - 对 DataFrameGroupBy 中的字符串使用 Pandas Rank
- sockets - 为什么我在 WebRTC 会议中收到 Websocket 错误?
- docusignapi - 有没有办法通过使用 DocuSign API 检查另一个单独的复选框来自动检查 A 组中的所有复选框
- office365 - MailKit 与 Microsoft 365 服务器的 SMTP OAuth 失败
- pandas - 在 pandas 数据框中以单行表示有效地聚合多行数据
- vb.net - 如何从文本框更新我的 Access 数据库
- php - 如何使用 PHP 将表格垂直翻转