I have a json file and I want to convert the data into a table with Javascript. I found some similar questions How to convert the following table to JSON with javascript? , loop through a json object, but they all use jQuery and show the table on html web. I just need a simple loop to insert row into the table. I tried 'append', 'insert' and 'insertRow', all not work. Could anyone give me a hint?
Json file:
{
"name": "lily",
"country": "china",
"age": 23
},
{
"name": "mike",
"country": "japan",
"age": 22
},
{
"name": "lucy",
"country": "korea",
"age": 25
}
My code:
var jdata = {};
jdata.cols = [
{
"id": "1",
"label": "name",
"type": "string"
},
{
"id": "2",
"label": "country",
"type":"string"
}
];
for(var i = 1; i < 3; i++){
row = [
{
"c": [
{
"v": json["hits"]["hits"][i]["_source"]["name"]
},
{
"v": json["hits"]["hits"][i]["_source"]["country"]
}
]
}
];
jdata.rows.insertRow(row);
}
Edit: Add expected output: change the json file to the following structure.
[
['lily', 'china'],
['mike', 'japan'],
['lucy', 'korea'],
]
I guess you need push (Or concat / push(...elements) if you want to add array of rows)
jdata.rows = [];
for(var i = 1; i < 3; i++){
row = [
{
"c": [
{
"v": json["hits"]["hits"][i]["_source"]["name"]
},
{
"v": json["hits"]["hits"][i]["_source"]["country"]
}
]
}
];
jdata.rows.push(row);
// for elements from row
// jdata.rows.push(...row)
}
There are a few errors in your code
The JSON needs to be an array so you can loop through each object to display.
insertRow() is a method from the Table object, jdata.rows is not a Table object but an array.
Since, you have used insertRow(), I have rewritten your code to display the table data using the Table Object methods. Here is a code snippet
Edit: You can use the push() method to create your required JSON structure. I have edited the code snippet to create your required JSON.
var jdata = {
cols: [{
"id": "1",
"label": "name",
"type": "string"
},
{
"id": "2",
"label": "country",
"type": "string"
}
],
rows: []
};
var persons = [{
"name": "lily",
"country": "china",
"age": 23
},
{
"name": "mike",
"country": "japan",
"age": 22
}, {
"name": "lucy",
"country": "korea",
"age": 25
}
];
var table = document.getElementById("table");
var header = table.createTHead();
var footer = table.createTFoot();
var rowHeader = header.insertRow(0);
jdata.cols.forEach((col, index) => {
var cell = rowHeader.insertCell(index);
cell.innerHTML = col.label;
});
persons.forEach((person, index) => {
var rowFooter = footer.insertRow(index);
rowFooter.insertCell(0).innerHTML = person.name;
rowFooter.insertCell(1).innerHTML = person.country;
jdata.rows.push([person.name, person.country]);
});
console.log(jdata.rows);
<table id="table">
</table>
Related
With some JavaScript, how can I transform a JSON from:
{
"d": {
"__count": "13",
"results": [
{
"__metadata": {
"id": "123"
},
"COAST": "East",
"STATUS": "done",
"COLOR": "blue",
}
]
}
}
TO
{
"__count": "13",
"data": [
{
"__metadata": {
"id": "123"
},
"COAST": "East",
"STATUS": "done",
"COLOR": "blue",
}
]
}
Basically removing the extra "d" parent and renaming results to data? I am using this in the context of vue-table in VueJS.
Assumed that you have the json saved in a variable 'data':
data = data.d
data.data = data.results
delete data.results
This function will do it.
function transform(json) {
var obj = JSON.parse(json);
obj.d.data = obj.d.result;
delete obj.d.result;
return JSON.stringify(obj.d);
}
One solution is to unserialize your JSON to have an object (JSON.parse()). Then to serialize only what you need (JSON.stringify()).
You can use a loop.
var res = [];
for(var k in jsonData){
res.push(jsonData[k]);
}
var jsonData = {
"d": {
"__count": "13",
"results": [
{
"__metadata": {
"id": "123"
},
"COAST": "East",
"STATUS": "done",
"COLOR": "blue",
}
]
}
};
console.log(jsonData);
var res = [];
for(var k in jsonData){
res.push(jsonData[k]);
}
console.log("result:");
console.log(res);
Fiddle Example
I want to convert this JSON data
var data = [
{
"computer": 24,
"brand": "Italy A",
"phone": 0,
"country": "Italy"
},
{
"brand": "Italy C",
"computer": 0,
"phone": 0,
"country": "Italy"
},
{
"brand": "Brazil B",
"computer": 0,
"phone": 22,
"country": "Brazil"
},
{
"computer": 0,
"brand": "Brazil D",
"phone": 62,
"country": "Brazil"
},
{
"computer": 34,
"brand": "US E",
"phone": 41,
"country": "US"
}
];
into a hierarchical form for a d3 graph:
{
"name": "categories",
"children": [
{
"name": "phone",
"children": [
{
"name": "US",
"children": [
{
"brand": "US E",
"size": 41
}
]
},
{
"name": "Brazil",
"children": [
{
"brand": "Brazil B",
"size": 22
},
{
"brand": "Brazil D",
"size": 62
}
]
},
{
"name": "Italy",
"children": []
}
]
},
{
"name": "computer",
"children": [
{
"name": "US",
"children": [
{
"brand": "US E",
"size": 34
}
]
},
{
"name": "Brazil",
"children": []
},
{
"name": "Italy",
"children": [
{
"brand": "Italy A",
"size": 24
}
]
}
]
}
]
}
I came up with this code to generate the format:
function group_children(data){
var categories = ["phone","computer"];
var countries = ["US","Brazil","Italy"];
var object = {name:"categories",children:[]};
for(var c =0; c < categories.length;c++){
object.children.push({"name":categories[c],children:[]});
for(var con = 0;con < countries.length;con++){
object.children[c].children.push({"name":countries[con],"children":[]});
}
}
for(var i = 0;i < data.length;i++){
var row = data[i];
for(var c =0; c < categories.length;c++){
for(var con = 0;con < countries.length;con++){
var cat_key = categories[c],
country_key = countries[con];
if(row[cat_key] > 0){
if(object.children[c].name == cat_key && row.country == country_key){ object.children[c].children[con].children.push({brand:row["brand"],size:row[cat_key]});
}
}
}
}
}
return object;
}
Is it possible , during the iteration, not to push a country into the brand or computer's children array if the country's children array is empty?
For example, these objects should be removed
// computer
{
"name": "Brazil",
"children": []
}
// phone:
{
"name": "Italy",
"children": []
}
Here's the part that push each country into each category's children array:
for(var c =0; c < categories.length;c++){
object.children.push({"name":categories[c],children:[]});
for(var con = 0;con < countries.length;con++){
object.children[c].children.push({"name":countries[con],"children":[]});
}
}
My approach is probably wrong, so any other suggestions converting the data into that hierarchical form is also appreciated.
Check this fiddle, is this what you're looking for? I decided to go for a different approach to the one you followed, hope you don't mind. I've commented the code so that it's clearer:
var result = {
name: "categories",
children: [{
"name": "phone",
"children": []
}, {
"name": "computer",
"children": []
}]
};
$.each(data, function (index, item) {// Go through data and populate the result object.
if (+item.computer > 0) { // Computer has items.
filterAndAdd(item, result.children[1], "computer");
}
if (+item.phone > 0) { // Phone has items.
filterAndAdd(item, result.children[0], "phone");
}
});
function filterAndAdd(item, result_place, type) {// Search and populate.
var i = -1;
$.each(result_place.children, function (index,a) {
if( a.name === item.country ) {
i = index;
return false;
}
});
if (i > -1) {// Country already exists, add to children array.
result_place.children[i].children.push({
"brand": item.brand,
"size": item[type]
});
} else {// Country doesn't exist, create it.
result_place.children.push({
"name": item.country,
"children": [{
"brand": item.brand,
"size": item[type]
}]
});
}
}
Hope it helps.
You have to use d3.nest() function to group array elements hierarchically. The documentation is available
here. Also go through this tutorial which could definitely help you to create hierarchical data.
That's not enough, you get hierarchical data in terms of key and value pairs. But if you want to convert into name and children, already a question on SO is asked, check this.
With your current approach you should iterate the data to find the empty ones, before pushing the countries, which would result in way more iteration than just simply iterating the result at the end to filter the empty ones.
Otherwise you should create the scruture in the same iterations of the data insertion, thus reducing the iterations to 1.
Here is the my first JSON Array format...
[
{
"id": "1234",
"caption": "caption1"
},
{
"id": "2345",
"caption": "caption2"
},
{
"id": "3456",
"caption": "caption3"
}
]
and here is another JSON Array Format
[
[
{
"id": "1234",
"value": "value11"
},
{
"id": "2345",
"value": "value12"
},
{
"id": "3456",
"value": "value13"
}
],
[
{
"id": "1234",
"value": "value21"
},
{
"id": "2345",
"value": "value22"
},
{
"id": "3456",
"value": "value23"
}
]
]
The above mentioned Two JSON Arrays, i need to compare each one with Id and need to format a new JSON Array with caption and value using javascript.
[
[
{
"caption" : "caption1",
"value":"value11"
},
{
"caption" : "caption2",
"value":"value12"
},
{
"caption" : "caption3",
"value":"value13"
}
],
[
{
"caption" : "caption1",
"value":"value21"
},
{
"caption" : "caption2",
"value":"value22"
},
{
"caption" : "caption3",
"value":"value23"
}
]
]
Please help me out.
You can do it in many ways. Below I show two variants:
Option 1: Pure JavaScript
In this example the program preindex first array for faster access to it data, and then loops over second array with map() function to create new array of arrays:
// Create index version of first array
var aix = {};
for(var i=0;i<arr1.length;i++) {
aix[arr1[i].id] = arr1[i].caption;
}
// Loop over array of arrays
var res1 = arr2.map(function(arr22){
return arr22.map(function(a){
return {caption:aix[a.id], value:a.value};
}
});
Option 2: Using special SQL library (Alasql)
Here, you can JOIN to arrays automatically with special SQL statement:
var res2 = arr2.map(function(a){
return alasql('SELECT arr1.caption, a.[value] \
FROM ? a JOIN ? arr1 USING id',[a,arr1]);
});
You can try these variants in working snippet below or play with it in jsFiddle.
(Disclaimer: I am the author of Alasql)
var arr1 = [
{
"id": "1234",
"caption": "caption1"
},
{
"id": "2345",
"caption": "caption2"
},
{
"id": "3456",
"caption": "caption3"
}
];
var arr2 = [
[
{
"id": "1234",
"value": "value11"
},
{
"id": "2345",
"value": "value12"
},
{
"id": "3456",
"value": "value13"
}
],
[
{
"id": "1234",
"value": "value21"
},
{
"id": "2345",
"value": "value22"
},
{
"id": "3456",
"value": "value23"
}
]
];
// JavaScript version
var aix = {};
for(var i=0;i<arr1.length;i++) {
aix[arr1[i].id] = arr1[i].caption;
}
var res1 = arr2.map(function(arr22){
return arr22.map(function(a){
return {caption:aix[a.id], value:a.value};
});
});
document.getElementById("res1").textContent = JSON.stringify(res1);
// Alasql version
var res2 = arr2.map(function(a){
return alasql('SELECT arr1.caption, a.[value] FROM ? a JOIN ? arr1 USING id',[a,arr1]);
});
document.getElementById("res2").textContent = JSON.stringify(res2);
<script src="http://alasql.org/console/alasql.min.js"></script>
<p>Varian 1: JavaScript</p>
<div id="res1"></div>
<p>Variant 2: Alasql</p>
<div id="res2"></div>
I am working on chart library,
I have json format, which will be coming from server, year and month format
{
"id": 1,
"name": "name1",
"present": "18",
"target": "18",
"status": "yellow"
}
Now I need to pass present and target values in a array format.
the data must be passed or parsed like below.
How to do I do this in javascript and jquery?
I tried all the available solutions, since I am new to the javascript world!
Expected result
var legendsText = [["present name1","target name1"]],
jsonFormat = [[18, 18],[15,18],[36, 18]];
FIDDLE
This is the fiddle our friend Eli Gassert has created, it is the closeset one
http://http://jsfiddle.net/Yq3DW/126/
but it is loading only present values of all 3 months
i want present and target values of each name.
For example
name1 link clicked, chart should load name1 present and target for all 3 months.
name2 link clicked, chart should load name2 present and target for all 3 months.
name3 link clicked, chart should load name3 present and target for all 3 months.
My JSON format which is coming dynamically from server
data={
"perspective": "something",
"year": "2014",
"measures": [
{
"id": 1,
"name": "some name",
"target": "200",
"responsiblePerson": null
},
{
"id": 2,
"name": "some name",
"target": "100",
"responsiblePerson": null
}
],
"values": {
"jan": [
{
"id": 1,
"name": "name1",
"present": "18",
"target": "18",
"status": "yellow"
},
{
"id": 2,
"name": "name2",
"present": "21",
"target": "22",
"status": "red"
},
{
"id": 3,
"name": "name3",
"present": "50",
"target": "50",
"status": "yellow"
}
],
"feb": [
{
"id": 1,
"name": "name1",
"present": "18",
"target": "18",
"status": "yellow"
},
{
"id": 2,
"name": "name2",
"present": "21",
"target": "22",
"status": "red"
},
{
"id": 3,
"name": "name3",
"present": "50",
"target": "50",
"status": "yellow"
}
],
"mar": [
{
"id": 1,
"name": "name1",
"present": "18",
"target": "18",
"status": "yellow"
},
{
"id": 2,
"name": "name2",
"present": "22",
"target": "22",
"status": "yellow"
},
{
"id": 3,
"name": "name3",
"present": "52",
"target": "50",
"status": "yellow"
}
]
}
}
HTML
<div id="chart"></div>
JS
var legendsText = [];
for(var i = 0; i != data.measures.length; ++i)
legendsText.push(data.measures[i].name);
legendsText = [legendsText];
var rows = [];
for(var i in data.values)
{
var row = []
for(var j = 0; j != data.values[i].length; ++j)
{
row.push(data.values[i][j].present);
}
rows.push(row);
}
rows = legendsText.concat(rows.sort(function (a, b) { }));
console.log(rows);
var chart = c3.generate({
bindto: '#chart',
data: {
rows: rows,
type: 'bar',
}
});
Any help is appreciated.
Here's an updated fiddle that transforms your data to the results: http://jsfiddle.net/Yq3DW/119/
Key aspects:
Your Legend Text can be gotten dynamically from your measures data. The format for the legendsText is an "array of arrays" so that's why I wrap it in [...] at the end of the loop.
var legendsText = [];
for(var i = 0; i != data.measures.length; ++i)
legendsText.push(data.measures[i].name);
legendsText = [legendsText];
Your rows can be gotten from your "values" data. But because it's not an array, like measures you need to use a for each loop instead of for loop:
var rows = [];
for(var i in data.values)
{
var row = []
for(var j = 0; j != data.values[i].length; ++j)
{
row.push(data.values[i][j].present);
}
rows.push(row);
}
EDIT: Updated question. To show just one label's worth of data but show both values for that data, and give nice labels: http://jsfiddle.net/Yq3DW/130/
The key here:
Switch to columns instead of rows, allowing one "row" of data to stand-in for the label indexer
Only add the data if the name in the value data matches the name you're searching for (had to update your data JSON so the names matched)
Had to use a 'tick' formatter to format the labels from 1-3 to jan, feb, mar. You can further customize it by using upper case/proper case conversions. That is outside the scope of this question and I'm not including it here. If you need further formatting, search for an answer first and if you can't find it, start a new Q.
Display a dynamic list of links to click that calls your loadData function to change the data in the chart between the various measure names
HTML:
<ul id="links"></ul>
<div id="chart"></div>
JS:
var $links = $('#links');
$links.html('');
for(var i = 0; i != data.measures.length; ++i)
{
(function()
{
var name = data.measures[i].name;
$('<li></li>')
.text(data.measures[i].name)
.click(function() { loadData(name); })
.appendTo($links);
})();
// legendsText.push(data.measures[i].name);
}
function loadData(name)
{
//var legendsText = [ ["present", "target"] ];
var columns = [ ["labels"], [ "present" ], [ "target" ]];
var labels = [];
for(var i in data.values)
{
var row = []
for(var j = 0; j != data.values[i].length; ++j)
{
if(data.values[i][j].name == name)
{
labels.push(i);
columns[0].push(labels.length);
columns[1].push(data.values[i][j].present);
columns[2].push(data.values[i][j].target);
}
}
//rows.push(row);
}
console.log(columns);
//rows = legendsText.concat(rows.sort(function (a, b) { }));
var chart = c3.generate({
bindto: '#chart',
data: {
x: 'labels',
columns: columns,
type: 'bar',
},
axis: {
x: {
tick: {
format: function(index) { return labels[index-1]; }
}
}
}
});
}
I have a question regarding JSON. I am using a jquery plugin which expected JSON structure as below :
[ { key: "Id" },
{ key: "Username" },
{ key: "Age" }
],
but my JSON looks like :
[{
"Employee1":
{
"ID": 43036,
"Name": XYZ,
"Age": 21
},
"Employee2":
{
"ID": 30436,
"Name": MNP,
"Age": 23
}
}]
Now I don't want to change my code, is there any solution so that I can pass Id , Name to my plugin json without using "Employee".
I need my JSON as :
[
{
"ID": 43036,
"Name": XYZ,
"Age": 21
},
{
"ID": 30436,
"Name": MNP,
"Age": 23
}
]
Thanks in Advance
Something like this?
var myObj = [{
"Employee1":
{
"ID": 43036,
"Name": XYZ,
"Age": 21
},
"Employee2":
{
"ID": 30436,
"Name": MNP,
"Age": 23
}
}];
var jsonObj = [];
$.each(myObj[0], function(key, val){
jsonObj.push({ key: val.ID });
jsonObj.push({ key: val.Name });
jsonObj.push({ key: val.Age });
});
What you need a simple function to push the values inside the object,
var data = [{
"Employee1": {
"ID": 43036,
"Name": 'XYZ',
"Age": 21
},
"Employee2": {
"ID": 30436,
"Name": 'MNP',
"Age": 23
}}];
data = data[0];
var output = [];
for (i in data) {
output.push(data[i]);
}
DEMO
Note: The JSON you posted was invalid, XYZ and MNP are string values and I suppose the other numbers too.. I leave the validation to you.