Reading JSON data and looping through it - javascript

I have 3 files
index.html
data.json
app.js
on my WAMP server. I wish to loop through the JSON data and update contents of the HTML file.
These are the contents of my files:
data.json
{
"user": [{
"goal": "HTML essential training",
"type": "Beginner",
"date": "20/07/2016"
}, {
"goal": "CSS essential training",
"type": "Beginner",
"date": "30/07/2016"
}, {
"goal": "CSS core concepts",
"type": "Intermediate",
"date": "10/08/2016"
}, {
"goal": "Javascript essential training",
"type": "Beginner",
"date": "20/08/2016"
}, {
"goal": "Object Oriented JS",
"type": "Advanced",
"date": "30/08/2016"
}]
}
app.js
var request = new XMLHttpRequest();
request.open('GET', 'data.json');
request.onreadystatechange = function() {
if ((request.readyState === 4) && (request.status === 200)) {
var items = JSON.parse(request.responseText);
console.log(items);
for (var key in items) {
console.log(key);
var output = "<tr><td><input type='checkbox' name='record'></td><td>" + items[key].goal + "</td><td>" + items[key].type + "</td><td>" + items[key].date + "</td></tr>";
console.log(output);
$("table tbody").append(output);
output = '';
}
}
}
request.send();
When i run this code, one row is created with all the values set to undefined. I think there's a problem with my looping logic.Please help me.

You are running into this since the object returned is a single key: value pair.
You need to access the user property which is an array.
your code
var items=JSON.parse(request.responseText);
The value you get after parsing the json string is the javascript object with key : 'user' and value : which is an array
Supposed to be
var data =JSON.parse(request.responseText);
var items = data.user; <-- this is an array of objects
// iterate using a for loop, since it is not an object technically
for(var i=0; i < items.length; i++) {

Take a look at the structure of your object:
{
"user": [
{
"goal": "HTML essential training",
"type": "Beginner",
"date": "20\/07\/2016"
},
{
"goal": "CSS essential training",
"type": "Beginner",
"date": "30\/07\/2016"
},
{
"goal": "CSS core concepts",
"type": "Intermediate",
"date": "10\/08\/2016"
},
{
"goal": "Javascript essential training",
"type": "Beginner",
"date": "20\/08\/2016"
},
{
"goal": "Object Oriented JS",
"type": "Advanced",
"date": "30\/08\/2016"
}
]
}
There's one key, with the value being an array.
You need a loop like this:
for (var key in items){if (items.hasOwnProperty(key)) {
for (var i in items[key]) {if (items[key].hasOwnProperty(i)){
console.log(items[key][i]);
var output="<tr><td><input type='checkbox' name='record'></td><td>" + items[key][i].goal + "</td><td>" + items[key][i].type + "</td><td>" + items[key][i].date + "</td></tr>";
console.log(output);
$("table tbody").append(output);
output='';
}}
}}

Related

How could one define the exact data types at any level of a nested object / array data-structure?

I am trying to define a "complex" object:
var tM = JSON.parse('{"version":"","series":[{"name":"","possModes":[],"instance":[{"date":"","mode":""}]}]}');
where all items of array "instance" should be objects of type
{"date":"","mode":""}
and all items of array "series" should be objects of type
{"name":"","possModes":[],"instance":[{"date":"","mode":""}]}
The problem is that only the items of index [0] are getting the proper properties and items of higher indexes are "undefined", so I cannot set them to their needed values.
I have also tried to define tM explicitly, like:
var Cinstance = new Object();
Cinstance.date = "";
Cinstance.mode = "";
var Cseries = new Object();
Cseries.name = '';
Cseries.possModes = [];
Cseries.instance = [new Object(Cinstance)];
var tM= new Object();
tM.version = "";
tM.series = [new Object(Cseries)];
and also like:
var tM = {series:
[{instance:
[{date:"",mode:""}
]
}
]
}
(this is a version reduced to my specific problem).
Of course, they both end up with the same result - only items of index [0] are defined.
The data structure provided by the OP ...
{
"version": "",
"series": [{
"name": "",
"possModes": [],
"instance": [{
"date": "",
"mode": ""
}]
}]
}
... does validate against the following JSON schema ...
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "My-Special-Schema-Or-Data-Structure-Title",
"description": "Whatever I have to say about my described structure",
"type": "object",
"properties": {
"version": {
"description": " ... ",
"type": "string"
},
"series": {
"description": " ... ",
"type": "array",
"minItems": 1,
"items": {
"description": " ... ",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"possModes": {
"description": " ... ",
"type": "array"
},
"instance": {
"description": " ... ",
"type": "array",
"minItems": 1,
"items": {
"description": " ... ",
"type": "object",
"properties": {
"date": {
"type": "string"
},
"mode": {
"type": "string"
}
},
"required": [
"date",
"mode"
]
}
}
},
"required": [
"name",
"possModes",
"instance"
]
}
}
},
"required": [
"version",
"series"
]
}
There is even a JSON Schema Generator one could start with. Passing the OP's originally provided data structure, one gets a solid base of a JSON Schema, one then can continue tailoring.

Create JSON object with same keys for API call

I'm trying to create a JSON object for an API call which has the following format:
....
"Key": "Value",
"Package": {
"Dimensions": {
"UnitOfMeasurement": {
"Code": "IN",
"Description": "inches"
},
"Length": "20",
"Width": "25",
"Height": "30"
},
"PackageWeight": {
"UnitOfMeasurement": {
"Code": "Lbs",
"Description": "pounds"
},
"Weight": "80"
}
},
"Package": {
"Dimensions": {
"UnitOfMeasurement": {
"Code": "IN",
"Description": "inches"
},
"Length": "15",
"Width": "24",
"Height": "27"
},
"PackageWeight": {
"UnitOfMeasurement": {
"Code": "Lbs",
"Description": "pounds"
},
"Weight": "50"
}
},
"Key": "Value",
....
I should add as many "Package" objects as needed. However, I've tried doing this in many different ways but every time that I parse the variable to be used the first objects get overwritten and I end up with only the last object.
This is what I'm trying at the moment, still with no luck:
var lineItems = '{';
for (var i=0;i<inputObject.packages.length;i++) {
lineItems += '"Package": {"PackagingType": {"Code": "02","Description": "Rate"},"Dimensions": {"UnitOfMeasurement": {"Code": "IN","Description": "inches"},"Length": ' + inputObject.packages[i][0].toString() + ',"Width": ' + inputObject.packages[i][1].toString() + ',"Height": ' + inputObject.packages[i][2].toString() + '},"PackageWeight": {"UnitOfMeasurement": {"Code": "Lbs","Description": "pounds"},"Weight": ' + inputObject.packages[i][3].toString() + '}}';
if (i !== inputObject.packages.length-1) {
lineItems += ',';
}
}
lineItems += '}';
lineItems = JSON.parse(lineItems);
How about numbering your packages, ie:
for (var i=0;i<inputObject.packages.length;i++) {
lineItems+='"Package" + i : { ... }'
}
edit: to get required result (as an array - because it's not JSON), here's an example:
var a=[];
var b={"package": {"c":100,"d":200,"e":300}}
var c={"package": {"c":800,"d":700,"e":600}}
a.push(b);
a.push(c);
console.log(a);

Rendering an HTML table from a JSON object without using jQuery

I am trying to take a JSON object output from Watson and parse it into an HTML table that can be added to a string, which is being sent as an email.
I tried using several plugins such as json2html, but could not seem to get any of them to work.
My JSON object looks like this:
WATSON TONE: {
"document_tone": {
"tone_categories": [
{
"tones": [
{
"score": 0.15756,
"tone_id": "anger",
"tone_name": "Anger"
},
{
"score": 0.192775,
"tone_id": "disgust",
"tone_name": "Disgust"
},
{
"score": 0.186713,
"tone_id": "fear",
"tone_name": "Fear"
},
{
"score": 0.255821,
"tone_id": "joy",
"tone_name": "Joy"
},
{
"score": 0.207131,
"tone_id": "sadness",
"tone_name": "Sadness"
}
],
"category_id": "emotion_tone",
"category_name": "Emotion Tone"
},
{
"tones": [
{
"score": 0,
"tone_id": "analytical",
"tone_name": "Analytical"
},
{
"score": 0,
"tone_id": "confident",
"tone_name": "Confident"
},
{
"score": 0,
"tone_id": "tentative",
"tone_name": "Tentative"
}
],
"category_id": "writing_tone",
"category_name": "Writing Tone"
},
{
"tones": [
{
"score": 0.803,
"tone_id": "openness_big5",
"tone_name": "Openness"
},
{
"score": 0.56,
"tone_id": "conscientiousness_big5",
"tone_name": "Conscientiousness"
},
{
"score": 0.149,
"tone_id": "extraversion_big5",
"tone_name": "Extraversion"
},
{
"score": 0.012,
"tone_id": "agreeableness_big5",
"tone_name": "Agreeableness"
},
{
"score": 0.387,
"tone_id": "neuroticism_big5",
"tone_name": "Emotional Range"
}
],
"category_id": "social_tone",
"category_name": "Social Tone"
}
]
}
}
and I'm trying to append it within a string that looks like this.
emailText = '<html><body><h2>Original Email: </h2><p>' + watsonInput + '</p> <h2>Results: </h2><p>' + jsonOutput + ' </p></body></html>';
I'm a little lost here and have taken a look at several previous questions on SO, but could not figure it out based on previous answers, as many people suggest to use various jQuery Plugins.
Any help/suggestions are appreciated,
Thanks
I've quickly made a crude example that shows you how to go about doing what you need. See below:
var json = '{ "watson_tone" : [' +
'{ "score": 0.1231 , "tone_id":"fear" },' +
'{ "score": 0.1235 , "tone_id":"sadness" },' +
'{ "score": 0.1236 , "tone_id":"disgust" } ]}';
// Parse the JSON so we can access what we need.
var parsed = JSON.parse(json);
// Get the amount of objects inside 'watson_tone' so we can loop through each one.
var count = Object.keys(parsed.watson_tone).length;
// Make some strings to include in our output.
var tableHeader = "<table><tr><th>score</th><th>tone_id</th></tr>";
var tableContent = "";
// Loop through the JSON and output each row in to a string.
for(i = 0; i < count; i++) {
tableContent = tableContent + "<tr><td>" + parsed.watson_tone[i].score + "</td><td>" + parsed.watson_tone[i].tone_id + "</tr>";
}
var tableFooter = "</table>";
// Get div and output the HTML. You can include these HTML strings straight in to your emailText variable.
document.getElementById("your_table").innerHTML = tableHeader + tableContent + tableFooter;
So you receive your JSON, then you parse it.
Next you count it, prepare your HTML output and loop through each record in the JSON (as required) and append this to the output.
Now you have a variable (or variables) containing the HTML that you need.
Good luck!

Getting value from JSON when it is an object in an array in an object in an array - if that makes sense?

I have been working on displaying values from a JSON feed and - with a great deal of thanks to help on the many previous posts I have read here - I can now write (display in browser) all the values of my objects in the main array BUT for the values of the 'name' objects which are 'nested' in an array > object > array > object > proprty:value structure (as below). Wondering if anyone might me kind enough to help me find a way to interate and display this level successfully - I feel I have run out of ideas on it at the moment :-(
Very thankful for an ideas. I have been using standard JavaScript not JQuery I should add.
var foo=[
{
"subjects":
[
"A1",
"SB2"
],
"title": "Box World",
"first_pub": "2013-12",
"characters":
[
{
"name":
{
"given": "Maxwell",
"honourific": "",
"family": "Smart"
},
"id": "MS34"
},
{
"name":
{
"given": "Samantha",
"honourific": "",
"family": "Stevens"
},
"id": "SS81"
} // end creators object 2
],
"publisher": "Galactic Publishing"
},
{
"subjects":
[
"A133",
"PB82"
],
"title": "Octonautica",
"first_pub": "2010",
"characters":
[
{
"name":
{
"given": "Peso",
"honourific": "Doctor",
"family": ""
},
"id": "MS34"
},
{
"name":
{
"given": "Barnacle",
"honourific": "Captain",
"family": ""
},
"id": "SS82"
}
],
"publisher": "Neptune House"
}
]
var obj_set = foo ;
for (var key in obj_set) {
document.write("\<h3\> Publication " + key + "\<\/h3\>" );
var obj = obj_set[key];
document.write("\<ol\>");
for (var prop in obj) {
document.write("\<li\>" + prop + " = " + obj[prop] + "\<\/li\>" );
}
document.write("\<\/ol\>");
}
//END MAIN KEY LOOP
Try this instead:
var i, j;
// iterate over main array foo
for (i=0; i<foo.length; i++) {
// iterate over characters array
for(j=0; j<foo[i].characters.length; j++) {
// each item contains an object "name"
var name = foo[i].characters[j].name;
console.log(name.honorific + ' ' + name.given + ' ' + name.family);
}
}

getJSON displays [object Object] rather than actual values

I have a JSON and I need to get this JSON and put in the html as a ul li list. It gets the value as object and displays [object Object] in html. If I modify the json then it works. so there is probably something wrong in my script where I am not able to loop throught he json file properly. Can some one help please:
MY JSON IS:
[
{
"us":"USA"
},
{
"fr":"FRANCE"
},
{
"es":"Spain"
},
{
"sa":"South Africa"
}
]
AND JS IS
<script>
$.getJSON('jsonfile', function(data) {
var items = [];
$.each(data ,function(key,val) {
items.push('<li id="'+ key +'">' + val +'</li>');
});
$('<ul />' , {
'class':'new-div',
html:items.join('')
}).appendTo('body');
});
</script>
UPDATED JSON:
[
{
"items":
{
"item":
[
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}
]
}
}
]
The data you're looping over is the array, which has objects. So your key will be 0, 1, etc., and the val will be the object at that position in the array.
Your JSON structure actually makes it a bit of a pain to output, because each of your objects only has one property, but the property name varies from object to object. You can do it, by looping over the object properties even though there's only one of them:
var items = [];
$.each(data ,function(outerKey, outerVal) { // <== Loops through the array
$.each(outerVal, function(key, val) { // <== "Loops" through each object's properties
items.push('<li id="'+ key +'">' + val +'</li>');
});
});
...but I'd change the JSON structure instead. For instance, assuming the keys are unique, your original code would work with this structure:
{
"us":"USA",
"fr":"FRANCE",
"es":"Spain",
"sa":"South Africa"
}

Categories