ak85
ak85

Reputation: 4264

Build json string from unordered list

I have the below unordered list

<ul>
    <li data-id="111" data-sub="0" data-url="home" data-active="1">Home</li>
    <li data-id="222" data-sub="0" data-url="about" data-active="1">About</li>
    <li data-id="333" data-sub="1" data-url="news" data-active="1">News
        <ul>
            <li data-id="444" data-sub="0" data-url="news/latest" data-active="1">Latest</li>
            <li data-id="555" data-sub="0" data-url="news/reports" data-active="1">Reports</li>
        </ul>
    </li>
</ul>

I want to get the data attributes and output it in JSON so that it appears in the same format as below

[{
    "active": 1,
    "url": "home",
    "sub": 0,
    "id": 111
}, {
    "active": 1,
    "url": "about",
    "sub": 0,
    "id": 222
}, {
    "active": 1,
    "url": "news",
    "sub": 1,
    "id": 333,
    "child": [{
        "active": 1,
        "url": "news/latest",
        "sub": 0,
        "id": 444
    }, {
        "active": 1,
        "url": "news/reports",
        "sub": 0,
        "id": 555
    }]
}]

Currently I have the below JS

<script>
    var mynav = [];
    $("li").each(function () {
          if($(this).children("ul").length) {
              $(this).data('child', '"' + $(this).data() + '"');
              mynav.push($(this).data());
       }
        mynav.push($(this).data());
    });
    mynav = JSON.stringify(mynav);
    console.log(mynav);
</script>

Which outputs the below.

[{
    "active": 1,
    "url": "home",
    "sub": 0,
    "id": 111
}, {
    "active": 1,
    "url": "about",
    "sub": 0,
    "id": 222
}, {
    "active": 1,
    "url": "news",
    "sub": 1,
    "id": 333,
    "child": "\"[object Object]\""
}, {
    "active": 1,
    "url": "news",
    "sub": 1,
    "id": 333,
    "child": "\"[object Object]\""
}, {
    "active": 1,
    "url": "news/latest",
    "sub": 0,
    "id": 444
}, {
    "active": 1,
    "url": "news/reports",
    "sub": 0,
    "id": 555
}]

My format is fine for a simple un ordered list by when a list item has additional sum items like my example I am not able to convert my list to the correct JSON format. What do I need to do to my JS to get it to format the sub lists the way I want them as well?

Upvotes: 1

Views: 855

Answers (3)

Manwal
Manwal

Reputation: 23816

The way you want to do this: DEMO

var mynav = [];
    $("#ulid").children("li").each(function () {
        var that = this;
          if($(that).children("ul").length) {
              var temp = [];/*I am CHILD array*/
              $(that).children("ul").find("li").each(function(){
                  temp.push($(this).data());
              });
              $(that).data().child = temp;
       }
        mynav.push($(that).data());
    });
    mynav = JSON.stringify(mynav, null, 4);
$('body').html('<pre>' + mynav + '</pre>');

Upvotes: 1

adeneo
adeneo

Reputation: 318182

Here's one way to do it

var nav = (function rec(el) {
    return el.map(function() {
        var o = $(this).data(),
            c = $(this).children('ul').children('li');

        if ( c.length > 0 ) o.child = rec(c);
        return o
    }).get();
})($(' body > ul > li'));

recursively traversing the children and building the JSON

FIDDLE

Upvotes: 3

Arun P Johny
Arun P Johny

Reputation: 388316

You can give an id to the top element like

<ul id="mynav">
    <li data-id="111" data-sub="0" data-url="home" data-active="1">Home</li>
    <li data-id="222" data-sub="0" data-url="about" data-active="1">About</li>
    <li data-id="333" data-sub="1" data-url="news" data-active="1">News
        <ul>
            <li data-id="444" data-sub="0" data-url="news/latest" data-active="1">Latest</li>
            <li data-id="555" data-sub="0" data-url="news/reports" data-active="1">Reports</li>
        </ul>
    </li>
</ul>

then

var nav = getNav($('#mynav'));

function getNav($ul) {
    return $ul.children('li').map(function () {
        var $this = $(this),
            obj = $this.data(),
            $ul = $this.children('ul');
        if ($ul.length) {
            obj.child = getNav($ul)
        }
        return obj;
    }).get()
}

Demo: Fiddle

Upvotes: 4

Related Questions