如何在Javascript(或Cof​​feescript)中将嵌套的JSON转换为嵌套的HTML列表?

时间:2013-03-27 11:25:56

标签: javascript jquery arrays json coffeescript

我有一些JSON数据(简单的对象数组)。

var input= [
    {
        "cat": "some",
        "id": "0"
    },
    {
        "cat": "some",
        "id": "1"
    },
    {
        "cat": "some/category",
        "id": "2"
    },
    {
        "cat": "some/category/sub",
        "id": "3"
    },
    {
        "cat": "some/other",
        "id": "4"
    },
    {
        "cat": "some/thing/different",
        "id": "5"
    },
    {
        "cat": "some/thing/different",
        "id": "6"
    },
    {
        "cat": "yet/another",
        "id": "7"
    }
]

我想根据类别生成嵌套的html列表:     

            
  • 一些             
                      
    • 0
    •                 
    • 1
    •                 
    • 类别                     
                                
      • 2
      •                         
      • 子                             
                                          
        • 3
        •                             
                                
      •                     
                      
    •                 
    • 其他                     
                                
      • 4
      •                     
                      
    •                 
    • 事                     
                                
      • 不同                             
                                          
        • 5
        •                                 
        • 6
        •                             
                                
      •                     
                      
    •             
            
  •         
  • 还             
                      
    • 另一                     
                                
      • 7
      •                     
                      
    •             
            
  •     

我的第一步是使用函数

创建空的嵌套对象
createNestedObject = function(base, names) {
  var  = 0;
  var results = [];
  while (i < names.length) {
    base = base[names[i]] = base[names[i]] || {};
    results.push(i++);
  }
  return results;
}

接下来,我通过分割“cat”字符串并在循环中推送“ids”来填充数据(例如some.category.sub.ids.push(7)) 最终结果是:

var output = 
{
    "some": {
        "ids": [
            "0",
            "1"
        ],
        "category": {
            "ids": [
                "2"
            ],
            "sub": {
                "ids": [
                    "3"
                ]
            }
        },
        "other": {
            "ids": [
                "4"
            ]
        },
        "thing": {
            "different": {
                "ids": [
                    "5",
                    "6"
                ]
            }
        },
        "yet": {
            "another": {
                "ids": [
                    "7"
                ]
            }
        }
    }
}

然而,这个结构有点问题,因为我事先并不知道密钥名称和嵌套深度。 如何从这里提供的“输出”或“输入”数据生成嵌套的html列表?

4 个答案:

答案 0 :(得分:2)

这个怎么样?

Example

<强> JS

function ToHTML(input){
    var html = '<ul>'; 

    for(var key in input){
        if(input[key] instanceof Array){
            for(var i = 0; i < input[key].length; i++){
                html += '<li>' + input[key][i] + '</li>';
            }
        }else{
            html += '<li>' + key + ToHTML(input[key]) + '</li>';
        }           
    }
    html += '</ul>';
    return html; 
}

function ToNestedObject(input){
    var i, y, len = input.length, parts, partsLen, obj = {}, prev;
    for(i = 0; i < len; i++){
        parts = input[i].cat.split('/'); 
        partsLen = parts.length;
        prev = obj; 
        for(y = 0; y < partsLen; y++){
            prev[parts[y]] = prev[parts[y]] || {};    
            prev = prev[parts[y]];
        }
        if(!prev.ids){
            prev.ids = []; 
        }
        prev.ids.push(input[i].id); 
    }
    return obj; 
}

var input= [
    {
        "cat": "some",
        "id": "0"
    },
    {
        "cat": "some",
        "id": "1"
    },
    {
        "cat": "some/category",
        "id": "2"
    },
    {
        "cat": "some/category/sub",
        "id": "3"
    },
    {
        "cat": "some/other",
        "id": "4"
    },
    {
        "cat": "some/thing/different",
        "id": "5"
    },
    {
        "cat": "some/thing/different",
        "id": "6"
    },
    {
        "cat": "yet/another",
        "id": "7"
    }
];

document.getElementById('test').innerHTML = ToHTML(ToNestedObject(input)); 

<强> HTML

<div id='test'></div>

答案 1 :(得分:1)

将数组转换为对象树

function buildTreeObject ( input ) {

        var obj = {}, n ;

        input.forEach( function( v ){
                var keys = v.cat.split('/'),
                    n = obj ;        

                keys.forEach( function( k ){        
                        if ( !n[k]) {
                            n[k] = {}; 
                        }                 
                        n = n[k];                 
                }); 

                n[ v.id ] = v.id ;                
        });

        return obj;
}

我们需要一个构建html的函数

function buildHtml( obj , ul ) {

    for (i in obj) {

        var li = document.createElement('li');
        li.innerHTML = i;
        ul.appendChild( li );

        if ( typeof(obj[i])== "object" ) {

            childUl = document.createElement('ul');
            li.appendChild( childUl ); 

            buildHtml(obj[i], childUl );            
        }  

    }
} 

并使用input(即你的数组)

进行html使用
var ul   = document.createElement('ul'),
    tree =  buildTreeObject( input ) ;

buildHtml( tree ,ul );

var div = document.createElement('div');    
div.appendChild( ul );

console.log( div.innerHTML );

打印所需的ul li列表

您可以在http://jsfiddle.net/r3RWL/

中看到结果

答案 2 :(得分:1)

由于你在标签下添加了jquery,我已经在jQuery中为你的问题编写了解决方案。这是代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    </head>
<body>
    <div id="someDiv">
    </div>
    <script>

    function prepareNestedStructure(input) {
        var output = {},
            catLevels,
            currentCat;

        $.each(input, function(index, catObject) {
            catLevels = catObject.cat.split('/');
            currentCat = output;

            $.each(catLevels, function(index, name) {
                if(!currentCat[name])
                    currentCat[name] = {};
                currentCat = currentCat[name];
            });

            currentCat[catObject.id] = catObject.id;
        });

        return output;
    }

    function fillList(parentListEl, node) {
        $.each(node, function(key, value) {
            parentListEl.append('<li>' + key + '</li>');

            if(jQuery.type(value) === 'object') {
                var childEl = $('<ul></ul>');
                parentListEl.append(childEl);
                fillList(childEl, value);
            }
        });
    }

    var input= [
        {
            "cat": "some",
            "id": "0"
        },
        {
            "cat": "some",
            "id": "1"
        },
        {
            "cat": "some/category",
            "id": "2"
        },
        {
            "cat": "some/category/sub",
            "id": "3"
        },
        {
            "cat": "some/other",
            "id": "4"
        },
        {
            "cat": "some/thing/different",
            "id": "5"
        },
        {
            "cat": "some/thing/different",
            "id": "6"
        },
        {
            "cat": "yet/another",
            "id": "7"
        }
    ];

    var output = prepareNestedStructure(input);

    var ulDomElement = $('<ul></ul>');
    fillList(ulDomElement, output);
    $('#someDiv').append(ulDomElement);

    </script>
</body>
</html>

答案 3 :(得分:0)

这是怎么回事?

transform_deeply_nested_object = (dno) ->
    result = ""
    for key, value of dno
        if value instanceof Array
            result += "<ul>"
            for elem in value
                result += "<li>" + elem + "</li>\n"
            result += "</ul>"
        else
            result += "<ul><li>" + key + "</li>"
            result += transform_deeply_nested_object value
            result += "</ul>"

注意:未经测试!

注意:这要求所有叶子始终是数组的元素。