How to generate nested json object from nested lis

2019-07-04 04:17发布

I would like to generate the following object:

var ideaBoard = {
     "Staff Retreat" : {
         "Games" : [
             {"title" : "Rockband", "details" : "1hr"},
             {"title" : "Texas Hold em", "details" : "30min"}
         ],
         "Talks" : [
             {"title" : "The Old You", "details" : "Dr. Smith"}
         ]
     }
}

from the following HTML:

<div id="data">
    <ul><span class="board-title">Staff Retreat</span>
        <li><span class="category-title">Games</span>
            <ul>
                <li>
                    <span class="title">Rockband</span>
                    <span class="details">1hr</span>
                </li>
                <li>
                    <span class="title">Texas Hold em</span>
                    <span class="details">30min</span>
                </li>
            </ul>
        </li>
        <li><span class="category-title">Talks</span>
            <ul>
                <li>
                    <span class="title">The Old You</span>
                    <span class="details">Dr. Smith</span>
                </li>
            </ul>
        </li>
    </ul>
</div>

I'm new to loops/arrays/objects - so I really appreciate the help!

I'm using jQuery elsewhere in this project, if it helps.

Thanks!

3条回答
何必那么认真
2楼-- · 2019-07-04 04:54

It is not optimized, but it works:

var result = {};
var node1;
var node2;
var node3;
var tmpObj = {};
$('#data > ul').each(function() {
    node1 = $(this);
    result[node1.find('.board-title').text()] = {};
    node1.find('.category-title').each(function() {
        node2 = $(this);
        result[node1.find('.board-title').text()][node2.text()] = [];
        node2.next('ul').children('li').each(function() {
            node3 = $(this);
            tmpObj = {};
            node3.children('span').each(function() {
                tmpObj[$(this).attr('class')] = $(this).text();
            });
            result[node1.find('.board-title').text()][node2.text()].push(tmpObj);
        })
    });
});
console.log(result);
查看更多
Summer. ? 凉城
3楼-- · 2019-07-04 05:10

There a multiple ways. Here is one:

var ideaBoard = {}
$('#data > ul').each(function() {
   var data = {}, // board data
       title = $(this).find('.board-title').text(); // board title

   // find categories
   $(this).find('> li > .category-title').each(function() {
        var category = $(this).text(), // category title

        // we can use map to create the array
        var category_data = $(this).next().children('li').map(function() {
            var tdata = {};

            // each span contains detailed data
            $(this).children('span').each(function() {
                tdata[this.className] = $(this).text();
            });

            return tdata;
        }).get();

        data[category] = category_data;
   });

  ideaBoard[title] = data;
});

DEMO

This will most likely break if you change the structure of the HTML. If you have a lot of data like this, this code might also be quite slow.

To learn about the methods used, have a look at the jQuery documentation.

查看更多
啃猪蹄的小仙女
4楼-- · 2019-07-04 05:20

How you are generating the HTML? If you are using PHP you could just pass the variables to JS rather than trying to read them later from HTML. For example if you have them in array, could use json_encode in PHP and then echo that in your page inside variables = jQuery.parseJSON(here);

Now if you cannot do this, and you really want to read it from HTML, you should then first select the id data with $('#data') and take its children(). Then use .each() for the children. Then put the child to object and then check its each children() with .each() and add them to your object. If you may have more than just those levels I recommend doing a recursive function for this.

PS: I dont think its proper HTML to put Span between UL and LI.

查看更多
登录 后发表回答