使用Javascript将嵌套的JSON转换为HTML嵌套列表

时间:2009-07-31 10:12:16

标签: javascript json list nested

我使用JSON(而不是XML)相当新,我目前正在使用Javascript来消化,解析和显示我返回的JSON数据。

我正在使用JSON2.js库并返回一些有效的JSON数据,代表一个相当简单的嵌套列表:

{
  "node":{
    "class":"folder",
    "title":"Test Framework",
    "node":{
      "class":"folder",
      "title":"Item 1",
      "node":{
        "class":"folder",
        "title":"Item 1.1",
        "node":{
          "class":"file",
          "title":"Item 1.1.a"
        }
      },
      "node":{
        "class":"folder",
        "title":"Item 1.2",
        "node":{
          "class":"file",
          "title":"Item 1.2.a"
        },
        "node":{
          "class":"file",
          "title":"Item 1.2.b"
        },
        "node":{
          "class":"file",
          "title":"Item 1.2.c"
        }
      },
      "node":{
        "class":"folder",
        "title":"Item 1.3",
        "node":{
          "class":"folder",
          "title":"Item 1.3.a",
          "node":{
            "class":"file",
            "title":"Item 1.3.a.i"
          },
          "node":{
            "class":"file",
            "title":"Item 1.3.a.ii"
          }
        }
      }
    },
    "node":{
      "class":"folder",
      "title":"Item 2",
      "node":{
        "class":"file",
        "title":"item 2.a"
      },
      "node":{
        "class":"file",
        "title":"Item 2.b"
      }
    }
  }
}

有没有人有任何指针可以快速将该批次转换为具有所有嵌套元素的UL?如果JSON中的“class”元素可以用作每个LI的类,那将会很酷。

非常感谢任何帮助。

谢谢,

戴夫。

3 个答案:

答案 0 :(得分:9)

你的json不适合你的任务。某些对象具有多个具有相同名称的属性(“节点”),因此它们相互重叠。您必须使用节点数组。这是一个工作数据结构和可以将其转换为嵌套列表的函数:

<!DOCTYPE HTML PUBLIC"-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title></title>
<script type="text/javascript">
function parseNodes(nodes) { // takes a nodes array and turns it into a <ol>
    var ol = document.createElement("OL");
    for(var i=0; i<nodes.length; i++) {
        ol.appendChild(parseNode(nodes[i]));
    }
    return ol;
}

function parseNode(node) { // takes a node object and turns it into a <li>
    var li = document.createElement("LI");
    li.innerHTML = node.title;
    li.className = node.class;
    if(node.nodes) li.appendChild(parseNodes(node.nodes));
    return li;
}

window.jsonData = [{
    "class": "folder",
    "title": "Test Framework",
    "nodes": [{
        "class": "folder",
        "title": "Item 1",
        "nodes": [{
            "class": "folder",
            "title": "Item 1.1",
            "nodes": [{
                "class": "file",
                "title": "Item 1.1.a"
            }]
        },
        {
            "class": "folder",
            "title": "Item 1.2",
            "nodes": [{
                "class": "file",
                "title": "Item 1.2.a"
            },
            {
                "class": "file",
                "title": "Item 1.2.b"
            },
            {
                "class": "file",
                "title": "Item 1.2.c"
            }]
        },
        {
            "class": "folder",
            "title": "Item 1.3",
            "nodes": [{
                "class": "folder",
                "title": "Item 1.3.a",
                "nodes": [{
                    "class": "file",
                    "title": "Item 1.3.a.i"
                },
                {
                    "class": "file",
                    "title": "Item 1.3.a.ii"
                }]
            }]
        }]
    },
    {
        "class": "folder",
        "title": "Item 2",
        "nodes": [{
            "class": "file",
            "title": "item 2.a"
        },
        {
            "class": "file",
            "title": "Item 2.b"
        }]
    }]
}];

</script>
</head>
<body>
    <input type="button" 
    onclick="document.body.appendChild(parseNodes(jsonData))"
    value="go" />
</body>
</html>

我可以添加此css以使项目编号与节点标题匹配:)

<style type="text/css">
ol { list-style-type: none }
ol ol { list-style-type: decimal }
ol ol ol { list-style-type: decimal }
ol ol ol ol { list-style-type: lower-alpha }
ol ol ol ol ol { list-style-type: lower-roman }
</style>

See it in action.

答案 1 :(得分:1)

这是一些相当简单的代码,为每个对象创建一个<ul>元素,每个部分创建一个<li>元素。如果您想添加特殊情况,可以添加快速检查以针对child等内容测试"class"变量。

function jsonToHtmlList(json) {
    return objToHtmlList(JSON.parse(json));
}

function objToHtmlList(obj) {
    if (obj instanceof Array) {
        var ol = document.createElement('ol');
        for (var child in obj) {
            var li = document.createElement('li');
            li.appendChild(objToHtmlList(obj[child]));
            ol.appendChild(li);
        }
        return ol;
    }
    else if (obj instanceof Object && !(obj instanceof String)) {
        var ul = document.createElement('ul');
        for (var child in obj) {
            var li = document.createElement('li');
            li.appendChild(document.createTextNode(child + ": "));
            li.appendChild(objToHtmlList(obj[child]));
            ul.appendChild(li);
        }
        return ul;
    }
    else {
        return document.createTextNode(obj);
    }
}

这不会完全符合您的要求,因为您的JSON没有意义。 JavaScript中的对象以及JSON是映射,因此您不能拥有多个具有相同名称的子项。 Cédric指出,你需要将多个“节点”变成一个数组。

答案 2 :(得分:0)

您可以自己遍历json结构并在需要时创建适当的<li>,但我建议您实现Composite Pattern。有关详细信息,请参阅link