Reputation: 4264
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
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
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
Upvotes: 3
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