Turning nested JSON into an HTML nested list with Javascript

后端 未结 3 1901
忘了有多久
忘了有多久 2021-02-06 13:03

I\'m fairly new to using JSON (as opposed to XML) and am currently working purely with Javascript to digest, parse and display my returned JSON data.

I\'m using the JSON

相关标签:
3条回答
  • 2021-02-06 13:32

    Your json is unsuited to your task. Some objects have several properties with the same name ("node"), so they are overriding one another. You have to use arrays of nodes instead. Here is a working data structure and the functions that can turn it into a nested list:

    <!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>
    

    And I can add this css to have the items numberings match the node titles :)

    <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.

    0 讨论(0)
  • 2021-02-06 13:35

    You can walk through your json structure by yourself and create appropriate <li> when needed, but I suggest you to implement Composite Pattern. See link for more details

    0 讨论(0)
  • 2021-02-06 13:37

    Here's some fairly simple code that creates a <ul> element for each object, and a <li> element for each portion. You can add a quick check to test the child variable against things like "class" if you want to add a special case.

    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);
        }
    }
    

    This won't do exactly what you want, because your JSON doesn't make sense. Objects in JavaScript, and therefore JSON, are maps, and so you can't have more than one child with the same name. You'll need to turn your multiple "node"s into an array, as Cédric points out.

    0 讨论(0)
提交回复
热议问题