There is a JSON data and I have displayed each key value as a column in the table.
I want to export data from JSON to each column as a selectbox.
i.e. I want to show all corresponding values of "country" in JSON as selectbox in COUNTRY column.
My JSON data
"kitap": [
{
"author": "Chinua Achebe",
"country": "Nigeria",
"imageLink": "images/things-fall-apart.jpg",
"language": "English",
"link": "https://en.wikipedia.org/wiki/Things_Fall_Apart\n",
"pages": 209,
"title": "Things Fall Apart",
"year": 1958
},
{
"author": "Hans Christian Andersen",
"country": "Denmark",
"imageLink": "images/fairy-tales.jpg",
"language": "Danish",
"link": "https://en.wikipedia.org/wiki/Fairy_Tales_Told_for_Children._First_Collection.\n",
"pages": 784,
"title": "Fairy tales",
"year": 1836
},
My Javascript
let table2 = document.getElementById("tr2")
var books = fetch("kitap.json")
.then(res=> res.json())
.then(veri => {for(let data in veri ) {
for(deger of veri[data]) {
select.innerHTML+= `
<td><option value="${deger.author}">${deger.author}</option></td>
<td><option value="${deger.country}">${deger.country}</option></td>
`
}
}})
How can i edit?
Do you mean something like this? A loop over the keys, then a loop for all the items for each key. Finally after aggregating into array, we do a <select> element using a simple utility function.
var obj = {"kitap":[{"author":"Chinua Achebe","country":"Nigeria","imageLink":"images\/things-fall-apart.jpg","language":"English","link":"https:\/\/en.wikipedia.org\/wiki\/Things_Fall_Apart\n","pages":209,"title":"Things Fall Apart","year":1958},{"author":"Hans Christian Andersen","country":"Denmark","imageLink":"images\/fairy-tales.jpg","language":"Danish","link":"https:\/\/en.wikipedia.org\/wiki\/Fairy_Tales_Told_for_Children._First_Collection.\n","pages":784,"title":"Fairy tales","year":1836}]}
function do_select(select, options, name) {
select.innerHTML = '<option>Choose ' + name + '</options>';
options.forEach(function(value) {
var z = document.createElement("option");
z.setAttribute("value", value);
z.innerText = value;
select.appendChild(z)
})
}
do_obj_selects(obj)
function do_obj_selects(obj) {
var arr = obj.kitap;
var keys = Object.keys(obj.kitap[0]);
var result = {}
keys.forEach(function(key) {
obj.kitap.forEach(function(item) {
result[key] = result[key] || []
result[key].push(item[key])
})
var sel_category = document.createElement("SELECT");
sel_category.setAttribute("id", "category");
document.body.appendChild(sel_category);
do_select(sel_category, result[key], key)
})
}
Related
I am fetching API into my Express server which has several JSON key value pairs in one array.
For Example:
[{
"quality": "best",
"url": "https://someurlhere.example/?someparameters"
},
{
"quality": "medium",
"url": "https://someurlhere1.example/?someparameters"
}]
And I want to create an array of JSON of that received data in this Format:
[{
"best": "https://someurlhere.example/?someparameters"
},
{
"medium": "https://someurlhere1.example/?someparameters"
}]
I have tried doing this by using for loop
for(let i=0; i < formats.length; i++){
arr.push({
`${formats[i].quality}` : `${formats[i].url}`
})
}
But it didn't work for me.
Please help me in achieving this.
Thanks in Advance :)
You could use the map function and create a new object from it.
For example:
let prevArr = [{
"quality": "best",
"url": "https://someurlhere.example/?someparameters"
}, {
"quality": "medium",
"url": "https://someurlhere1.example/?someparameters"
}]; // Replace with your array
let newArr = [];
let obj = {};
prevArr.map(function(x) {
obj = {};
obj[x["quality"]] = x.url;
newArr.push(obj);
});
const input = [{
"quality": "best",
"url": "https://someurlhere.example/?someparameters"
}, {
"quality": "medium",
"url": "https://someurlhere1.example/?someparameters"
}];
const result = input.map((v, i) => {
return {
[v["quality"]]: v["url"]
}
});
console.log(result)
I have this JSON Response from API call
[
{
"id": 20599,
"name": "Deliver",
"options": [
{
"id": 63775,
"name": "Item",
"dataType": "SelectMultiOption",
"required": false,
"options": [
{
"id": 426,
"name": "Towels"
},
{
"id": 427,
"name": "Toothbrush"
},
{
"id": 428,
"name": "Pillow"
}
]
}
]
}
]
I am using this code to get the id of the service "Deliver"
var data = JSON.parse(responseBody);
var loop_count = 0
for (count = 0; count < data.length; count++)
{
if (data[count].name == "Deliver")
{
var job_id = data[count].id;
postman.setEnvironmentVariable("service_id", job_id);
}
}
The questions are:
How can I get value from array "options", I need to get the "id":
63775 and store as "item_id" and the "name":"Item" as "item_name" postman variables.
Then I need to select the "options" nested in record
"Item" and select the option "name": "Toothbrush" and store in postman
variable "svc_optn_optn_name" and it's "id" stored in
"svc_optn_optn_id"
Here I am giving my own suggestion for your problem with few lines of code. I am not sure, how are you going to use these values. I also don't know if the outer options array will always have 1 item or more. I have just tried to satisfy your questions.
Please ask/comment, if you have more doubts or I am wrong.
I have created a function getAllPostmanDataFrom(obj) which takes object as parameter which is the value of data[count], gathers necessary info in other object postmanObj and returns it to the caller.
function getAllPostmanDataFrom(obj) {
const item_id = obj.options[0].id;
const item_name = obj.options[0].name;
const svc_optn_optn_name = obj.options[0].options[1].name;
const svc_optn_optn_id = obj.options[0].options[1].id;
const postmanObj = {item_id, item_name, svc_optn_optn_id, svc_optn_optn_name}; // Return object
return postmanObj;
}
var data = [
{
"id": 20599,
"name": "Deliver",
"options": [
{
"id": 63775,
"name": "Item",
"dataType": "SelectMultiOption",
"required": false,
"options": [
{
"id": 426,
"name": "Towels"
},
{
"id": 427,
"name": "Toothbrush"
},
{
"id": 428,
"name": "Pillow"
}
]
}
]
}
]
var count = 0;
var obj = data[count];
var postmanObj = getAllPostmanDataFrom(obj);
//var {item_id, item_name, svc_optn_optn_id} = postmanObj;
console. log(postmanObj)
/*
console.log(item_id);
console.log(item_name);
console.log(svc_optn_optn_id);
console.log(svc_optn_optn_name);
*/
Finally, you can use values contained in postmanObj as follows:.
postman.setEnvironmentVariable("item_id", postmanObj.item_id);
postman.setEnvironmentVariable("item_name", postmanObj.item_name);
And so on.
This is the solution
var data = JSON.parse(responseBody);
variable named as data
var loop_count = 0
for (count = 0; count < data.length; count++)
{
if (data[count].name == "Deliver")
{
var job_id = data[count].id;
postman.setEnvironmentVariable("service_id", job_id);
var job1_name = data[count].options[0].name;
postman.setEnvironmentVariable("item_name", job1_name);
var job2_id = data[count].options[0].id;
postman.setEnvironmentVariable("item_id", job2_id);
var job3_id = data[count].options[0].options[1].id;
postman.setEnvironmentVariable("svc_optn_optn_id", job3_id);
var job4_name = data[count].options[0].options[1].name;
postman.setEnvironmentVariable("svc_optn_optn_name", job4_name);
}
const data = JSON.parse(responseBody);
data.forEach(item => {
console.log(item.id); // deliver object id.
item.options.forEach(option => {
console.log(`Option Id ${option.id}`); // option id
postman.setEnvironmentVariable("service_id", option.id);
option.options(optionItem => {
if(optionItem.name == 'Toothbrush'){
postman.setEnvironmentVariable("svc_optn_optn_name", optionItem.name);
postman.setEnvironmentVariable("svc_optn_optn_id", optionItem.id);
}
});
});
});
I have a CSV file which needs to be converted into a Javascript object / JSON file. Doesn't really matter which since I'll be be handling the data in JS anyway and either is fine.
So for instance this:
name,birthday/day,birthday/month,birthday/year,house/type,house/address/street,house/address/city,house/address/state,house/occupants
Lily Haywood,27,3,1995,Igloo,768 Pocket Walk,Honolulu,HI,7
Stan Marsh,19,10,1987,Treehouse,2001 Bonanza Street,South Park,CO,2
should become this:
[
{
"name": "Lily Haywood",
"birthday": {
"day": 27,
"month": 3,
"year": 1995
},
"house": {
"type": "Igloo",
"address": {
"street": "768 Pocket Walk",
"city": "Honolulu",
"state": "HI"
},
"occupants": 7
}
},
{
"name": "Stan Marsh",
"birthday": {
"day": 19,
"month": 10,
"year": 1987
},
"house": {
"type": "Treehouse",
"address": {
"street": "2001 Bonanza Street",
"city": "South Park",
"state": "CO"
},
"occupants": 2
}
}
]
This is what I have came up with:
function parse(csv){
function createEntry(header){
return function (record){
let keys = header.split(",");
let values = record.split(",");
if (values.length !== keys.length){
console.error("Invalid CSV file");
return;
}
for (let i=0; i<keys.length; i++){
let key = keys[i].split("/");
let value = values[i] || null;
/////
if (key.length === 1){
this[key] = value;
}
else {
let newKey = key.shift();
this[newKey] = this[newKey] || {};
//this[newKey][key[0]] = value;
if (key.length === 1){
this[newKey][key[0]] = value;
}
else {
let newKey2 = key.shift();
this[newKey][newKey2] = this[newKey][newKey2] || {};
this[newKey][newKey2][key[0]] = value;
//if (key.length === 1){}
//...
}
}
/////
}
};
}
let lines = csv.split("\n");
let Entry = createEntry(lines.shift());
let output = [];
for (let line of lines){
entry = new Entry(line);
output.push(entry);
}
return output;
}
My code works, however there is an obvious flaw to it: for each layer it goes down into (e.g. house/address/street), I have to manually write repeated if / else statements.
Is there a better way to write it? I know this involves recursion or iteration of some kind but I just can't seem to figure out how.
I've searched around SO but most questions seem to be on doing it in Python instead of JS.
As far as possible I wish to have this done in vanilla JS without any other libraries.
You can achieve the intended results by creating the Object recursively.
Look at the code below:
var csv = [
"name,birthday/day,birthday/month,birthday/year,house/type,house/address/street,house/address/city,house/address/state,house/occupants",
"Lily Haywood,27,3,1995,Igloo,768 Pocket Walk,Honolulu,HI,7",
"Stan Marsh,19,10,1987,Treehouse,2001 Bonanza Street,South Park,CO,2"
];
var attrs = csv.splice(0,1);
var result = csv.map(function(row) {
var obj = {};
var rowData = row.split(',');
attrs[0].split(',').forEach(function(val, idx) {
obj = constructObj(val, obj, rowData[idx]);
});
return obj;
})
function constructObj(str, parentObj, data) {
if(str.split('/').length === 1) {
parentObj[str] = data;
return parentObj;
}
var curKey = str.split('/')[0];
if(!parentObj[curKey])
parentObj[curKey] = {};
parentObj[curKey] = constructObj(str.split('/').slice(1).join('/'), parentObj[curKey], data);
return parentObj;
}
console.log(result);
.as-console-wrapper{max-height: 100% !important; top:0}
constructObj() function basically constructs the resultant object recursively by looking at the column name, so if the column name contains the / like in house/address/street it will create a key in the object by the name house and then recursively calls itself for the rest of the remaining keys in string i.e. address/street/. The recursion ends when no more / are left in the string and then it simply assigns the value in that key and returns the result object.
You can map over your records and create the objects on the fly :
let records = ['Lily Haywood,27,3,1995,Igloo,768 Pocket Walk,Honolulu,HI,7',
'Stan Marsh,19,10,1987,Treehouse,2001 Bonanza Street,South Park,CO,2']
let output = records.map( record => {
let arr = record.split(',')
return {
"name": arr[0],
"birthday": {
"day": parseInt(arr[1]),
"month": parseInt(arr[2]),
"year": parseInt(arr[3])
},
"house": {
"type": arr[4],
"address": {
"street": arr[5],
"city": arr[6],
"state": arr[7]
},
"occupants": parseInt(arr[8])
}
}
})
console.log(output)
I have received a JSON response like
[
{"no":001, "location": "England", "year":"2017", "month":"4", "amount":"1000"},
{"no":002, "location": "Italy", "year":"2017", "month":"3", "amount":"8000"},
{"no":001, "location": "England", "year":"2016", "month":"2", "amount":"9000"},
{"no":001, "location": "England", "year":"2016", "month":"11","amount":"12000"}
];
I need to make it
[
{"no":001, "location": "England", "year":"2016", "amount2":"9000", "amount11":"12000"},
{"no":001, "location": "England", "year":"2017", "amount4":"1000"},
{"no":002, "location": "Italy", "year":"2017", "amount3":"8000"}
];
that is based on the no converting multiple records to one with amounts specific to months and common info ie location but same no should have different records corresponding to the year.
General advice: Collect the information by ID in another datastructure. I suppose this is an Accumulator Pattern.
var rows = [
{"no":"001","month":"4","amount":"1000"},
{"no":"002","month":"3","amount":"8000"},
{"no":"001","month":"2","amount":"9000"},
{"no":"001","month":"11","amount":"12000"}
];
var results = [];
var idToResultsObject = {};
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
var id = row['no'];
if (typeof idToResultsObject[id] == 'undefined')
idToResultsObject[id] = { 'no' : id };
idToResultsObject[id]['location'] = row['location'];
idToResultsObject[id]['amount' + row['month']] = row['amount'];
}
for (var id in idToResultsObject) {
results.push(idToResultsObject[id]);
}
console.log(results);
Surely there is a nicer way to store this.
Here is updated es5 code to match your latest edit of the question:
(I'm still not sure I understand what you want from no so for now I leave it as number which it is in input (not in quotes)
var input = [
{"no":001, "location": "England", "year":"2017", "month":"4", "amount":"1000"},
{"no":002, "location": "Italy", "year":"2017", "month":"3", "amount":"8000"},
{"no":001, "location": "England", "year":"2016", "month":"2", "amount":"9000"},
{"no":001, "location": "England", "year":"2016", "month":"11","amount":"12000"}
];
/*
[
{"no":001, "location": "England", "year":"2016", "amount2":"9000", "amount11":"12000"},
{"no":001, "location": "England", "year":"2017", "amount4":"1000"},
{"no":002, "location": "Italy", "year":"2017", "amount3":"8000"}
];
*/
var output = input.reduce( function(result, cur) {
var ref = result.find( function(row) {
return row.no === cur.no && row.location === cur.location && cur.year === row.year }
);
if (ref) {
ref["amount"+cur.month] = cur.amount;
} else {
var newRow = { "no": cur.no, "location": cur.location, "year": cur.year };
newRow["amount"+cur.month] = cur.amount;
result.push(newRow);
}
return result;
},[])
console.log(output);
As others have suggested, it's really a bad way to design those objects. But this code does what you want (es6 syntax):
var input = [
{"no":001,"month":"4","amount":"1000"},
{"no":002,"month":"3","amount":"8000"},
{"no":001,"month":"2","amount":"9000"},
{"no":001,"month":"11","amount":"12000"}
];
/*
[
{"no":001, "amount2":"9000", "amount4":"1000", "amount11":"12000"},
{"no":002, "amount3":"8000"}
];
*/
var output = input.reduce( (result, cur) => {
var ref = result.find( row => row.no === cur.no);
if (ref) {
ref["amount"+cur.month] = cur.amount;
} else {
var newRow = { "no": cur.no };
newRow["amount"+cur.month] = cur.amount;
result.push(newRow);
}
return result;
},[])
console.log(output);
es5 syntax
var input = [
{"no":001,"month":"4","amount":"1000"},
{"no":002,"month":"3","amount":"8000"},
{"no":001,"month":"2","amount":"9000"},
{"no":001,"month":"11","amount":"12000"}
];
/*
[
{"no":001, "amount2":"9000", "amount4":"1000", "amount11":"12000"},
{"no":002, "amount3":"8000"}
];
*/
var output = input.reduce( function(result, cur) {
var ref = result.find( function(row) { return row.no === cur.no });
if (ref) {
ref["amount"+cur.month] = cur.amount;
} else {
var newRow = { "no": cur.no };
newRow["amount"+cur.month] = cur.amount;
result.push(newRow);
}
return result;
},[])
console.log(output);
I need to convert a large CSV data set to JSON, however the output should be a JSON dictionary like this:
var products = {
"crystal": {
"description": "This is a crystal",
"price": "2.95"
},
"emerald": {
"description": "This is a emerald",
"price": "5.95"
}
};
This is what the CSV table would look like:
I am using a script referenced here to generate the JSON:
var csv = require('csv')
var fs = require('fs')
var f = fs.createReadStream('Fielding.csv')
var w = fs.createWriteStream('out.txt')
w.write('[');
csv()
.from.stream(f, {columns:true})
.transform(function(row, index) {
return (index === 0 ? '' : ',\n') + JSON.stringify(row);
})
.to.stream(w, {columns: true, end: false})
.on('end', function() {
w.write(']');
w.end();
});
However the output from that script is created in this format:
[
{
"name": "crystal",
"description": "This is a crystal",
"price": "2.95"
},
{
"name": "emerald",
"description": "This is a emerald",
"price": "5.95"
}
]
How would I modify the script to get my desired "dictionary" format?
All you need to do is loop over the array and use item.name as key for your dictionary object
var products ={};
data.forEach(function(item){
products[item.name] = item;
});
This will leave the name property in the item but that shouldn't be an issue
I found csv parser library most useful:
var csvText=`status,path,name,ext,checksum,size,document_service_id,document_service_path,message
success,./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE1.txt,expE1.txt,txt,38441337865069eabae7754b29bb43e1,414984,8269f7e3-3221-49bb-bb5a-5796cf208fd1,/neuroinftest/20170215/expE1.txt,
success,./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE10.txt,expE10.txt,txt,f27e46979035706eb0aaf58c26e09585,368573,2c94ed19-29c9-4660-83cf-c2148c3d6f61,/neuroinftest/20170215/expE10.txt,
success,./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE2.txt,expE2.txt,txt,e1040d9546423c823944120de0e5c46c,333308,b3898f5d-1058-4cf3-acf9-76759117b810,/neuroinftest/20170215/expE2.txt,
`
var csv = require('csv');
csv.parse(csvText, {columns: true}, function(err, data){
console.log(JSON.stringify(data, null, 2));
});
In variable csvText I have my comma-separated file, with the first line serving as a header. I use the parse function and I'm passing the {columns: true} to indicated that the first line has the headers. Second parameter in the callback function (data) has the object with keys being the headers and the values being the corresponding csv cells. I use JSON.stringify to print it nicely and the result object looks like this (it puts it into an array):
[
{
"status": "success",
"path": "./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE1.txt",
"name": "expE1.txt",
"ext": "txt",
"checksum": "38441337865069eabae7754b29bb43e1",
"size": "414984",
"document_service_id": "8269f7e3-3221-49bb-bb5a-5796cf208fd1",
"document_service_path": "/neuroinftest/20170215/expE1.txt",
"message": ""
},
{
"status": "success",
"path": "./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE10.txt",
"name": "expE10.txt",
"ext": "txt",
"checksum": "f27e46979035706eb0aaf58c26e09585",
"size": "368573",
"document_service_id": "2c94ed19-29c9-4660-83cf-c2148c3d6f61",
"document_service_path": "/neuroinftest/20170215/expE10.txt",
"message": ""
},
{
"status": "success",
"path": "./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE2.txt",
"name": "expE2.txt",
"ext": "txt",
"checksum": "e1040d9546423c823944120de0e5c46c",
"size": "333308",
"document_service_id": "b3898f5d-1058-4cf3-acf9-76759117b810",
"document_service_path": "/neuroinftest/20170215/expE2.txt",
"message": ""
}
]
UPD: This array can easily be turned into the object you need with reduce:
var res_obj = data.reduce(function(acc, cur, i) {
acc[cur.name] = cur;
return acc;
}, {});
In my case I use the name property as a key. Make sure it's unique.
I think something like this would work :
var products_arr = [{"name":"crystal","description":"This is a crystal","price":"2.95"},
{"name":"emerald","description":"This is a emerald","price":"5.95"}]
var products = {};
for (var i = 0, l = products_arr.length ; i < l ; ++i) {
var x = products_arr[i];
var name = x.name
delete x.name; // deletes name property from JSON object
products[name] = x;
}
This will output :
{
"crystal": {
"description": "This is a crystal",
"price": "2.95"
},
"emerald": {
"description": "This is a emerald",
"price": "5.95"
}
}
If you would like to modify your specific code, you could change the line
return (index === 0 ? '' : ',\n') + JSON.stringify(row);
to
var clonedRow = JSON.parse(JSON.stringify(row));
var key = clonedRow['name'];
delete clonedRow['name'];
var newRow = {};
newRow[key] = clonedRow;
return (index === 0 ? '' : ',\n') + JSON.stringify(newRow);
This creates a new object for each row, modifying the structure according to your requirement.
Your best bet is to use PapaParse, a powerful csv parser/dumper. It supports streams, various string encodings, header row, and it's fast.