Problem Overview
Let's say I have a shipment of candy. The shipment has a number of boxes, and each box has a number of unique candy types. Every box has a unique id, different from every other box; the same is true for candy types. Furthermore, a candy has additional traits, like color, flavor and quantity.
Example Code
Take the following HTML example:
<div class="shipment">
<div class="box" data-boxid="a">
<div class="candy" data-candyid="1" data-color="orange" data-flavor="orange" data-qty="7">
<!-- unimportant content -->
</div>
<div class="candy" data-candyid="2" data-color="red" data-flavor="strawberry" data-qty="4">
<!-- unimportant content -->
</div>
</div>
<div class="box" data-boxid="b">
<div class="candy" data-candyid="3" data-color="green" data-flavor="lime">
<!-- unimportant content -->
</div>
</div>
</div>
Previous Attempts
I've seen similar examples of table parsing with jQuery's .map()
function, and I've also seen mention of .each()
, but I've been unable to generate any working code.
Desired Output
I want to generate (with jQuery) a JSON object similar to the following:
{
"shipment": {
"a": {
"1": {
"color": "orange",
"flavor": "orange",
"qty": "7"
},
"2": {
"color": "red",
"flavor": "strawberry",
"qty": "4"
}
},
"b": {
"3": {
"color": "green",
"flavor": "lime"
}
}
}
}
Additional Notes
My app already uses jQuery extensively, so it seems like a logical tool for the job. However, if plain 'ol JavaScript is a more appropriate choice, feel free to say so.
The HTML is always going to be well-formed and always going to follow a the format specified. However, in some cases, information may be inplete. Note that the third candy had no quantity specified, so quantity was simply ignored while building the object.
Problem Overview
Let's say I have a shipment of candy. The shipment has a number of boxes, and each box has a number of unique candy types. Every box has a unique id, different from every other box; the same is true for candy types. Furthermore, a candy has additional traits, like color, flavor and quantity.
Example Code
Take the following HTML example:
<div class="shipment">
<div class="box" data-boxid="a">
<div class="candy" data-candyid="1" data-color="orange" data-flavor="orange" data-qty="7">
<!-- unimportant content -->
</div>
<div class="candy" data-candyid="2" data-color="red" data-flavor="strawberry" data-qty="4">
<!-- unimportant content -->
</div>
</div>
<div class="box" data-boxid="b">
<div class="candy" data-candyid="3" data-color="green" data-flavor="lime">
<!-- unimportant content -->
</div>
</div>
</div>
Previous Attempts
I've seen similar examples of table parsing with jQuery's .map()
function, and I've also seen mention of .each()
, but I've been unable to generate any working code.
Desired Output
I want to generate (with jQuery) a JSON object similar to the following:
{
"shipment": {
"a": {
"1": {
"color": "orange",
"flavor": "orange",
"qty": "7"
},
"2": {
"color": "red",
"flavor": "strawberry",
"qty": "4"
}
},
"b": {
"3": {
"color": "green",
"flavor": "lime"
}
}
}
}
Additional Notes
My app already uses jQuery extensively, so it seems like a logical tool for the job. However, if plain 'ol JavaScript is a more appropriate choice, feel free to say so.
The HTML is always going to be well-formed and always going to follow a the format specified. However, in some cases, information may be inplete. Note that the third candy had no quantity specified, so quantity was simply ignored while building the object.
Share Improve this question edited Jul 18, 2024 at 17:02 VLAZ 29.1k9 gold badges62 silver badges84 bronze badges asked Mar 28, 2013 at 20:08 PeterPeter 4,1516 gold badges40 silver badges59 bronze badges 2-
A bination of
.each()
and.find()
should do the trick. Start at the top and work your way to the inner properties. – Blazemonger Commented Mar 28, 2013 at 20:13 -
I've tried something similar, but I believe I encountered working with children of children (e.g., nested
.each()
functions). Could you please post an example? I'm not necessarily asking for a plete solution (after all, this is a fictional example). Just a step in the right direction. – Peter Commented Mar 28, 2013 at 20:15
3 Answers
Reset to default 8This generates what you asked for:
var json = {};
$('.shipment').each(function(i,a) {
json.shipment = {};
$(a).find('.box').each(function(j,b) {
var boxid = $(b).data('boxid');
json.shipment[boxid] = {};
$(b).find('.candy').each(function(k,c) {
var $c = $(c),
candyid = $c.data('candyid'),
color = $c.data('color'),
flavor = $c.data('flavor'),
qty = $c.data('qty');
json.shipment[boxid][candyid] = {};
if (color) json.shipment[boxid][candyid].color = color;
if (flavor) json.shipment[boxid][candyid].flavor = flavor;
if (qty) json.shipment[boxid][candyid].qty = qty;
});
});
});
http://jsfiddle/mblase75/D22mD/
As you can see, at each level it uses .each()
to loop through the elements matching a certain class and then .find().each()
to loop through the desired children. In between, .data()
is used to grab the desired data-
attributes and the json object is built level by level.
Is this close to what you are looking for? – http://jsfiddle/4RPHL/
I have used data()
and JSON.stringify
to create the json.
Be sure to check your console where I have logged the output.
$(".candy").each(function() {
console.log(JSON.stringify($(this).data()))
});
Nice problem! Thanks to Chris' post I was able to get this to work.
var shipments = [],
shipment = {},
boxes = {},
candy = {};
$(".shipment").each(function() {
var shipment = {},
boxes = {};
$(this).children().each(function(){
var boxdata = $(this).data();
candy = {};
$(this).children().each(function(){
var candydata = $(this).data();
candy[candydata["candyid"]] = {
color: candydata["color"],
flavor: candydata["flavor"],
qty: candydata["qty"]
};
boxes[boxdata["boxid"]] = candy;
});
//console.log(JSON.stringify(boxes)); // works
});
shipment = {shipment: boxes};
shipments.push(shipment); // for multiples
});
console.log(JSON.stringify(shipments[0]));
console.log(shipments.length); // 1 for the example html above