递归JSON生成函数

Recursive JSON Generation Function

这会有点啰嗦,但这里是:

我正在编写两个单独的 Web 应用程序:一个用于生成带有大量数据和格式信息的 JSON 对象,另一个用于将 JSON 对象转换为格式良好的 HTML 页面进行查看。我目前遇到的特定问题是嵌套列表。

对于查看应用程序,我编写了一个递归函数,它将解析提供的 javascript 对象并为具有任意大小的嵌套元素的列表创建 HTML。

function createUnorderedList(object) {
    var ul = $('<ol>');

    for (var i = 0; i < object.length; i++) {
        if (object[i].children === undefined) {
            ul.append($('<li>').text(object[i].value));
        } else {
            ul.append(
            $('<li>').html(
            object[i].value + "<ul>" + createUnorderedList(object[i].children) + "</ul>"));
        }
    }

    return ul.html();
}

可以在此处查看该函数的 jsfiddle:jsfiddle: Recursive HTML List Generation

现在,我需要为事物的 JSON 创建端创建一个函数。在尝试并未能全神贯注于如何递归执行此操作后,我决定使用一个更线性的函数,参见此处:

function createList( array ) {
    var json = { "value": [] } ;
    var k = 0 ;
    if(array[array.length-1] === "") array.pop() ;
    for(var i=0; i<array.length; i++ ){
        json.value.push( { "value": array[i] } ) ;
        for(var j=i+1; j<array.length; j++) {
            if(array[j].charAt(0) === '\t') {
                array[j] = array[j].replace( /\t/, '' ) ;
                i++;
                if(json.value[k].children === undefined)
                    $.extend( json.value[k], { children : [] } ) ;
                json.value[k].children.push( { "value": array[j] } ) ;
            } else { k++; j=array.length; }
        }
    }
    return json ;
}

jsfiddle: JSON List Generation.

这个函数只能处理一个数量级的嵌套列表,目前应该足够了,但并不理想。我怎样才能使这个函数能够生成具有任意大小的嵌套元素的 json 对象?

谢谢。

经过深思熟虑,我找到了解决方案。

首先,我更改了您的代码,为每个值创建一个 <li>。 children是<li>后的<ul>.

function createUnorderedList(object) {
    var ul = $('<ul>');
    for (var i = 0; i < object.length; i++) {
        ul.append($('<li>').text(object[i].value));
        if (object[i].children) {
            ul.append($('<ul>').html(createUnorderedList(object[i].children)));
        }
    }
    return ul.html();
}

然后我创建了一个递归搜索所有元素的函数。 <ul> 是它前面 <li> 的 child。

var createJSONRecursive = function(elem, arr) {
    var childNodes = elem.childNodes;
    var nodeTmp;
    for (var i = 0; i<childNodes.length; i++) {
        var node = {};
        var tagName = childNodes[i].tagName;
        if (tagName == 'LI') {
            node.value = childNodes[i].innerHTML;
            if (i < childNodes.length - 1 && childNodes[i+1].tagName == 'UL') {
                nodeTmp = node;
            }
            else {
                arr.push(node);
            }
        }
        else if (tagName == 'UL') {
            nodeTmp.children = [];
            createJSONRecursive(childNodes[i], nodeTmp.children);        
            arr.push(nodeTmp);
        }        
    }    
}

var createJSON = function(elem) {
    var json = {value:[]}
    createJSONRecursive(elem, json.value);
    return json;    
}

var json = createJSON(document.getElementById('div'));

这里是fiddle:https://jsfiddle.net/8qc2mcyz/2/

编辑::起初我误解了你的问题。

这是将 ul 层次结构解析为对象的方法(查看 JS 控制台以查看解析出的内容):

function itemsToHierarchy(node) {
    return $(node).find('> ul > li').toArray().map(function (item) {
        return {
            value: item.childNodes[0].textContent,
            children: itemsToHierarchy(item)
        };
    });
}

console.log(itemsToHierarchy($('#list')));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<!-- leaving the HTML scrunched up to save space -->
<div id="list"><ul><li>Item 1<ul><li>Item 1.1</li></ul></li><li>Item 2</li><li>Item 3<ul><li>Item 3.1</li><li>Item 3.2<ul><li>Item 3.2.1<ul><li>Item 3.2.1.1</li></ul></li></ul></li></ul></li><li>Item 4<ul><li>Item 4.1</li><li>Item 4.2</li></ul></li><li>Item 5<ul><li>Item 5.1</li></ul></li></ul></div>

起初我以为您是在寻求有关 createList() 功能的帮助。这是适用于任何嵌套深度的递归版本:

function getItems( array, depth ) {
    depth = depth || 0;
    var items = [],
        item = array.shift();

    while (item && countTabs(item) === depth) {
        items.push({
            value: item.replace(/^\t*/, ''),
            children: getItems(array, depth + 1)
        });
        item = array.shift();
    }

    if (item) { // not at this depth
        array.unshift(item);
    }

    return items;    
}

function countTabs(value) {
    return value.match(/^\t*/)[0].length;
}

从中返回的值可用于构建 HTML,如下所示:

function createUnorderedList(items) {
    return $('<ul>').append($.map(items, function (item) {
        var li = $('<li>').text(item.value);

        if (item.children.length) {
            li.append(createUnorderedList(item.children));
        }

        return li;
    }));        
}

完整解决方案:https://jsfiddle.net/1930t20f/