【问题标题】:How can I create a nested JSON object that mirrors a nested HTML form?如何创建反映嵌套 HTML 表单的嵌套 JSON 对象?
【发布时间】:2020-10-10 00:36:37
【问题描述】:

我有一个与此类似的 HTML 表单(请注意,它是由选项卡、可选字段集和字段元素组织的):

  • div.tab1
    • div.fieldset3
      • div.container308
      • div.container314
      • div.fieldset4
        • div.container309
        • div.container310
  • div.tab2
    • div.fieldset1
      • div.container311
      • div.fieldset2
        • div.container313
        • div.container312
  • div.tab3
    • div.container315
    • div.container316

每个div 是一个或多个input 元素的容器,但对于这个问题,我将重点放在容器上。

我正在尝试write a JavaScript function which would "walk" a specified HTML element and produce a JSON object in this format(请注意基于表单的选项卡、字段集和输入元素形成的嵌套):

   {
        "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;
};

我尝试切换到use serializeArray() with reduce(),但是that took off like a lead balloon

【问题讨论】:

    标签: javascript jquery json


    【解决方案1】:

    您好,据我了解,您必须在那里进行递归,因为您不知道它的级别,所以这里有一个示例,希望对您有所帮助。

    Recursion Mapping Tree

    function copyTree(originalTree){
        return originalTree.map((elem, index) => ({
          id: 'div.'+elem.id,
          content: !elem.content ? [] : this.copyTree(elem.content),
        }));
      }
    

    编辑: 我误解了你想要的东西,这里有一些你期望得到的东西,我希望这可以帮助你。
    代码的一些解释: 我使用 querySelectorAll 是因为它返回一个可以迭代的 NodeList,[...arr] 的原因是

    如果对象是可迭代的,它将从对象中创建一个数组。 更多示例请转到filter or map 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());
    });

    【讨论】:

    • 我没有关注...copyTree() 函数如何“读取”HTML DOM 以构建 JSON 对象?
    • @JeromyFrench 我错过了理解你的问题我编辑了它,对不起。
    猜你喜欢
    • 1970-01-01
    • 2021-10-02
    • 2017-02-14
    • 2017-12-22
    • 2023-02-17
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多