Altering array in .then statement (javascript) - javascript

In a double for loop I am looping through different values where I test if specific value returns an error. Predefined function returns promise and it is all okay, if I need it once. But I need a way to store all errors (errors array) and all correct states (corrects array) and hardware I am using does not allow dynamically adding text to screen so I am using arrays. But i cannot find a way to do it in .then block. I was searching for a solution online but could not find one that would solve my problem.
for (var i = 0; i < idarray.length; i++) {
type = idarray[i];
for (var j = 0; j < maxValues[i]; j++) {
//console.log("Type: ",type);
//here i send new command with type and value
var sethbt = myLibrary.NewCommand(uuid, "Param", {
"Data": [{
"Type": type, //number
"Control": 1,
"Value": j.toString() //string
}]
})
//here i read the value of type
var hbt = myLibrary.NewCommand(uuid, "Param", {
"Data": [{
"Type": type,
"Control": 0,
"Value": ""
}]
})
//hbt returns a promise where i get the value, if control==2 it is error, otherwise
//it is ok
hbt.then(function(data) {
obj = JSON.parse(data);
if (obj[0].Control == 2) {
var text = "ERROR: Type: \"" + obj[0].Type + "\" --> Value:\"" + obj[0].Value + "\"";
//here i want to add error to array of errors, but change is not seen
//out of .then block
errors.push(text);
} else {
corrects.push("OK: Type: \"" + obj[0].Type + "\" --> Value:\"" + obj[0].Value + "\"");
}
});
}

Related

How to export nested json object to csv in javascript? [duplicate]

I have a link that opens up JSON data in the browser, but unfortunately I have no clue how to read it. Is there a way to convert this data using JavaScript in CSV format and save it in JavaScript file?
The data looks like:
{
"count": 2,
"items": [{
"title": "Apple iPhone 4S Sale Cancelled in Beijing Amid Chaos (Design You Trust)",
"description": "Advertise here with BSA Apple cancelled its scheduled sale of iPhone 4S in one of its stores in China\u2019s capital Beijing on January 13. Crowds outside the store in the Sanlitun district were waiting on queues overnight. There were incidents of scuffle between shoppers and the store\u2019s security staff when shoppers, hundreds of them, were told that the sales [...]Source : Design You TrustExplore : iPhone, iPhone 4, Phone",
"link": "http:\/\/wik.io\/info\/US\/309201303",
"timestamp": 1326439500,
"image": null,
"embed": null,
"language": null,
"user": null,
"user_image": null,
"user_link": null,
"user_id": null,
"geo": null,
"source": "wikio",
"favicon": "http:\/\/wikio.com\/favicon.ico",
"type": "blogs",
"domain": "wik.io",
"id": "2388575404943858468"
}, {
"title": "Apple to halt sales of iPhone 4S in China (Fame Dubai Blog)",
"description": "SHANGHAI \u2013 Apple Inc said on Friday it will stop selling its latest iPhone in its retail stores in Beijing and Shanghai to ensure the safety of its customers and employees. Go to SourceSource : Fame Dubai BlogExplore : iPhone, iPhone 4, Phone",
"link": "http:\/\/wik.io\/info\/US\/309198933",
"timestamp": 1326439320,
"image": null,
"embed": null,
"language": null,
"user": null,
"user_image": null,
"user_link": null,
"user_id": null,
"geo": null,
"source": "wikio",
"favicon": "http:\/\/wikio.com\/favicon.ico",
"type": "blogs",
"domain": "wik.io",
"id": "16209851193593872066"
}]
}
The closest I could find was: Convert JSON format to CSV format for MS Excel
But it downloads in a CSV file, I store it in a variable, the whole converted data.
Also would like to know how to change escape characters: '\u2019' back to normal.
I tried this code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>JSON to CSV</title>
<script src="http://code.jquery.com/jquery-1.7.1.js" type="text/javascript"></script>
<script type="text/javascript">
var json3 = {
"count": 2,
"items": [{
"title": "Apple iPhone 4S Sale Cancelled in Beijing Amid Chaos (Design You Trust)",
"description": "Advertise here with BSA Apple cancelled its scheduled sale of iPhone 4S in one of its stores in China’s capital Beijing on January 13. Crowds outside the store in the Sanlitun district were waiting on queues overnight. There were incidents of scuffle between shoppers and the store’s security staff when shoppers, hundreds of them, were told that the sales [...]Source : Design You TrustExplore : iPhone, iPhone 4, Phone",
"link": "http://wik.io/info/US/309201303",
"timestamp": 1326439500,
"image": null,
"embed": null,
"language": null,
"user": null,
"user_image": null,
"user_link": null,
"user_id": null,
"geo": null,
"source": "wikio",
"favicon": "http://wikio.com/favicon.ico",
"type": "blogs",
"domain": "wik.io",
"id": "2388575404943858468"
},
{
"title": "Apple to halt sales of iPhone 4S in China (Fame Dubai Blog)",
"description": "SHANGHAI – Apple Inc said on Friday it will stop selling its latest iPhone in its retail stores in Beijing and Shanghai to ensure the safety of its customers and employees. Go to SourceSource : Fame Dubai BlogExplore : iPhone, iPhone 4, Phone",
"link": "http://wik.io/info/US/309198933",
"timestamp": 1326439320,
"image": null,
"embed": null,
"language": null,
"user": null,
"user_image": null,
"user_link": null,
"user_id": null,
"geo": null,
"source": "wikio",
"favicon": "http://wikio.com/favicon.ico",
"type": "blogs",
"domain": "wik.io",
"id": "16209851193593872066"
}
]
}
//var objJson = JSON.parse(json3.items);
DownloadJSON2CSV(json3.items);
function DownloadJSON2CSV(objArray) {
var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
var str = '';
for (var i = 0; i < array.length; i++) {
var line = '';
for (var index in array[i]) {
line += array[i][index] + ',';
}
line.slice(0, line.Length - 1);
str += line + '\r\n';
}
$('div').html(str);
}
</script>
</head>
<body>
<div></div>
</body>
</html>
But it doesn't seem to work. Can someone please help?
A more elegant way to convert json to csv is to use the map function without any framework:
var json = json3.items
var fields = Object.keys(json[0])
var replacer = function(key, value) { return value === null ? '' : value }
var csv = json.map(function(row){
return fields.map(function(fieldName){
return JSON.stringify(row[fieldName], replacer)
}).join(',')
})
csv.unshift(fields.join(',')) // add header column
csv = csv.join('\r\n');
console.log(csv)
Output:
title,description,link,timestamp,image,embed,language,user,user_image,user_link,user_id,geo,source,favicon,type,domain,id
"Apple iPhone 4S Sale Cancelled in Beijing Amid Chaos (Design You Trust)","Advertise here with BSA Apple cancelled its scheduled sale of iPhone 4S in one of its stores in China’s capital Beijing on January 13. Crowds outside the store in the Sanlitun district were waiting on queues overnight. There were incidents of scuffle between shoppers and the store’s security staff when shoppers, hundreds of them, were told that the sales [...]Source : Design You TrustExplore : iPhone, iPhone 4, Phone","http://wik.io/info/US/309201303","1326439500","","","","","","","","","wikio","http://wikio.com/favicon.ico","blogs","wik.io","2388575404943858468"
"Apple to halt sales of iPhone 4S in China (Fame Dubai Blog)","SHANGHAI – Apple Inc said on Friday it will stop selling its latest iPhone in its retail stores in Beijing and Shanghai to ensure the safety of its customers and employees. Go to SourceSource : Fame Dubai BlogExplore : iPhone, iPhone 4, Phone","http://wik.io/info/US/309198933","1326439320","","","","","","","","","wikio","http://wikio.com/favicon.ico","blogs","wik.io","16209851193593872066"
Update ES6 (2016)
Use this less dense syntax and also JSON.stringify to add quotes to strings while keeping numbers unquoted:
const items = json3.items
const replacer = (key, value) => value === null ? '' : value // specify how you want to handle null values here
const header = Object.keys(items[0])
const csv = [
header.join(','), // header row first
...items.map(row => header.map(fieldName => JSON.stringify(row[fieldName], replacer)).join(','))
].join('\r\n')
console.log(csv)
Ok I finally got this code working:
<html>
<head>
<title>Demo - Covnert JSON to CSV</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript" src="https://github.com/douglascrockford/JSON-js/raw/master/json2.js"></script>
<script type="text/javascript">
// JSON to CSV Converter
function ConvertToCSV(objArray) {
var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
var str = '';
for (var i = 0; i < array.length; i++) {
var line = '';
for (var index in array[i]) {
if (line != '') line += ','
line += array[i][index];
}
str += line + '\r\n';
}
return str;
}
// Example
$(document).ready(function () {
// Create Object
var items = [
{ name: "Item 1", color: "Green", size: "X-Large" },
{ name: "Item 2", color: "Green", size: "X-Large" },
{ name: "Item 3", color: "Green", size: "X-Large" }];
// Convert Object to JSON
var jsonObject = JSON.stringify(items);
// Display JSON
$('#json').text(jsonObject);
// Convert JSON to CSV & Display CSV
$('#csv').text(ConvertToCSV(jsonObject));
});
</script>
</head>
<body>
<h1>
JSON</h1>
<pre id="json"></pre>
<h1>
CSV</h1>
<pre id="csv"></pre>
</body>
</html>
Thanks alot for all the support to all the contributors.
Praney
Very nice solution by praneybehl, but if someone wants to save the data as a csv file and using a blob method then they can refer this:
function JSONToCSVConvertor(JSONData, ReportTitle, ShowLabel) {
//If JSONData is not an object then JSON.parse will parse the JSON string in an Object
var arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData;
var CSV = '';
//This condition will generate the Label/Header
if (ShowLabel) {
var row = "";
//This loop will extract the label from 1st index of on array
for (var index in arrData[0]) {
//Now convert each value to string and comma-seprated
row += index + ',';
}
row = row.slice(0, -1);
//append Label row with line break
CSV += row + '\r\n';
}
//1st loop is to extract each row
for (var i = 0; i < arrData.length; i++) {
var row = "";
//2nd loop will extract each column and convert it in string comma-seprated
for (var index in arrData[i]) {
row += '"' + arrData[i][index] + '",';
}
row.slice(0, row.length - 1);
//add a line break after each row
CSV += row + '\r\n';
}
if (CSV == '') {
alert("Invalid data");
return;
}
//this trick will generate a temp "a" tag
var link = document.createElement("a");
link.id = "lnkDwnldLnk";
//this part will append the anchor tag and remove it after automatic click
document.body.appendChild(link);
var csv = CSV;
blob = new Blob([csv], { type: 'text/csv' });
var csvUrl = window.webkitURL.createObjectURL(blob);
var filename = (ReportTitle || 'UserExport') + '.csv';
$("#lnkDwnldLnk")
.attr({
'download': filename,
'href': csvUrl
});
$('#lnkDwnldLnk')[0].click();
document.body.removeChild(link);
}
If anyone wanted to download it as well.
Here is an awesome little function that will convert an array of JSON objects to csv, then download it.
downloadCSVFromJson = (filename, arrayOfJson) => {
// convert JSON to CSV
const replacer = (key, value) => value === null ? '' : value // specify how you want to handle null values here
const header = Object.keys(arrayOfJson[0])
let csv = arrayOfJson.map(row => header.map(fieldName =>
JSON.stringify(row[fieldName], replacer)).join(','))
csv.unshift(header.join(','))
csv = csv.join('\r\n')
// Create link and download
var link = document.createElement('a');
link.setAttribute('href', 'data:text/csv;charset=utf-8,%EF%BB%BF' + encodeURIComponent(csv));
link.setAttribute('download', filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
Then call it like this:
this.downloadCSVFromJson(`myCustomName.csv`, this.state.csvArrayOfJson)
I just wanted to add some code here for people in the future since I was trying to export JSON to a CSV document and download it.
I use $.getJSON to pull json data from an external page, but if you have a basic array, you can just use that.
This uses Christian Landgren's code to create the csv data.
$(document).ready(function() {
var JSONData = $.getJSON("GetJsonData.php", function(data) {
var items = data;
const replacer = (key, value) => value === null ? '' : value; // specify how you want to handle null values here
const header = Object.keys(items[0]);
let csv = items.map(row => header.map(fieldName => JSON.stringify(row[fieldName], replacer)).join(','));
csv.unshift(header.join(','));
csv = csv.join('\r\n');
//Download the file as CSV
var downloadLink = document.createElement("a");
var blob = new Blob(["\ufeff", csv]);
var url = URL.createObjectURL(blob);
downloadLink.href = url;
downloadLink.download = "DataDump.csv"; //Name the file here
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
});
});
Edit: It's worth noting that JSON.stringify will escape quotes in quotes by adding \". If you view the CSV in excel, it doesn't like that as an escape character.
You can add .replace(/\\"/g, '""') to the end of JSON.stringify(row[fieldName], replacer) to display this properly in excel (this will replace \" with "" which is what excel prefers).
Full Line: let csv = items.map(row => header.map(fieldName => (JSON.stringify(row[fieldName], replacer).replace(/\\"/g, '""'))).join(','));
There are multiple options available to reuse the existing powerful libraries that are standards based.
If you happen to use D3 in your project, then you can simply invoke:
d3.csv.format or d3.csv.formatRows functions to convert an array of objects into csv string.
d3.csv.formatRows gives you greater control over which properties are converted to csv.
Please refer to d3.csv.format and d3.csv.formatRows wiki pages.
There are other libraries available too like jquery-csv, PapaParse. Papa Parse has no dependencies - not even jQuery.
For jquery based plugins, please check this.
Try these Examples
Example 1:
JsonArray = [{
"AccountNumber": "123",
"AccountName": "abc",
"port": "All",
"source": "sg-a78c04f8"
}, {
"Account Number": "123",
"Account Name": "abc",
"port": 22,
"source": "0.0.0.0/0",
}]
JsonFields = ["Account Number","Account Name","port","source"]
function JsonToCSV(){
var csvStr = JsonFields.join(",") + "\n";
JsonArray.forEach(element => {
AccountNumber = element.AccountNumber;
AccountName = element.AccountName;
port = element.port
source = element.source
csvStr += AccountNumber + ',' + AccountName + ',' + port + ',' + source + "\n";
})
return csvStr;
}
Example2 :
JsonArray = [{
"AccountNumber": "1234",
"AccountName": "abc",
"inbound": [{
"port": "All",
"source": "sg-a78c04f8"
},
{
"port": 22,
"source": "0.0.0.0/0",
}]
}]
JsonFields = ["Account Number", "Account Name", "port", "source"]
function JsonToCSV() {
var csvStr = JsonFields.join(",") + "\n";
JsonArray.forEach(element => {
AccountNumber = element.AccountNumber;
AccountName = element.AccountName;
element.inbound.forEach(inboundELe => {
port = inboundELe.port
source = inboundELe.source
csvStr += AccountNumber + ',' + AccountName + ',' + port + ',' + source + "\n";
})
})
return csvStr;
}
You can even download the csv file using the following code :
function downloadCSV(csvStr) {
var hiddenElement = document.createElement('a');
hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csvStr);
hiddenElement.target = '_blank';
hiddenElement.download = 'output.csv';
hiddenElement.click();
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>JSON to CSV</title>
<script src="http://code.jquery.com/jquery-1.7.1.js" type="text/javascript"></script>
</head>
<body>
<h1>This page does nothing....</h1>
<script type="text/javascript">
var json3 = {
"count": 2,
"items": [{
"title": "Apple iPhone 4S Sale Cancelled in Beijing Amid Chaos (Design You Trust)",
"description": "Advertise here with BSA Apple cancelled its scheduled sale of iPhone 4S in one of its stores in China’s capital Beijing on January 13. Crowds outside the store in the Sanlitun district were waiting on queues overnight. There were incidents of scuffle between shoppers and the store’s security staff when shoppers, hundreds of them, were told that the sales [...]Source : Design You TrustExplore : iPhone, iPhone 4, Phone",
"link": "http://wik.io/info/US/309201303",
"timestamp": 1326439500,
"image": null,
"embed": null,
"language": null,
"user": null,
"user_image": null,
"user_link": null,
"user_id": null,
"geo": null,
"source": "wikio",
"favicon": "http://wikio.com/favicon.ico",
"type": "blogs",
"domain": "wik.io",
"id": "2388575404943858468"
},
{
"title": "Apple to halt sales of iPhone 4S in China (Fame Dubai Blog)",
"description": "SHANGHAI – Apple Inc said on Friday it will stop selling its latest iPhone in its retail stores in Beijing and Shanghai to ensure the safety of its customers and employees. Go to SourceSource : Fame Dubai BlogExplore : iPhone, iPhone 4, Phone",
"link": "http://wik.io/info/US/309198933",
"timestamp": 1326439320,
"image": null,
"embed": null,
"language": null,
"user": null,
"user_image": null,
"user_link": null,
"user_id": null,
"geo": null,
"source": "wikio",
"favicon": "http://wikio.com/favicon.ico",
"type": "blogs",
"domain": "wik.io",
"id": "16209851193593872066"
}
]
};
const items = json3.items
const replacer = (key, value) => value === null ? '' : value // specify how you want to handle null values here
const header = Object.keys(items[0])
let csv = items.map(row => header.map(fieldName => JSON.stringify(row[fieldName], replacer)).join(','))
csv.unshift(header.join(','))
csv = csv.join('\r\n')
var link = document.createElement("a");
link.id="lnkDwnldLnk";
document.body.appendChild(link);
blob = new Blob([csv], { type: 'text/csv' });
var csvUrl = window.webkitURL.createObjectURL(blob);
var filename = 'UserExport.csv';
jQuery("#lnkDwnldLnk")
.attr({
'download': filename,
'href': csvUrl
});
jQuery('#lnkDwnldLnk')[0].click();
document.body.removeChild(link);
</script>
</body>
</html>
An elegant way to convert object array to CSV:
const convertToCsv = (arr) => {
const keys = Object.keys(arr[0]);
const replacer = (_key, value) => value === null ? '' : value;
const processRow = row => keys.map(key => JSON.stringify(row[key], replacer)).join(',');
return [ keys.join(','), ...arr.map(processRow) ].join('\r\n');
};
To download it as file:
const downloadFile = (fileName, data) => {
var link = document.createElement('a');
link.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(data));
link.setAttribute('download', fileName);
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
I found the accepted answer extremely useful but needed my solution to work with unstructured json objects.
I have modified the accepted answer to work with an array of unstructured objects of varying size and schema.
Input:
[
{
"name": "Item 1",
"color": "Green",
"sizerange": {
"max": "X-Large",
"min": "X-Small"
}
},
{
"name": "Item 2",
"color": "Green",
"size": "X-Large",
"owner": {
"name": "Bill",
"address": {
"line1": "1 test st",
"suburb": "testville"
}
}
},
{
"name": "Item 3",
"color": "Green",
"sizes": [
"X-Large",
"Large",
"Small"
]
}
]
Output:
"name","color","sizerange.max","sizerange.min","size","owner.name","owner.address.line1","owner.address.suburb","sizes.0","sizes.1","sizes.2"
"Item 1","Green","X-Large","X-Small","","","","","","",""
"Item 2","Green","","","X-Large","Bill","1 test st","testville","","",""
"Item 3","Green","","","","","","","X-Large","Large","Small"
// JSON to CSV Converter
//https://www.codegrepper.com/code-examples/javascript/javascript+array+to+csv+string
function objectToCSVRow(dataObject) {
var dataArray = [];
for (var o in dataObject) {
var innerValue = typeof dataObject[o] == 'undefined' ? '' : dataObject[o].toString();
var result = innerValue.replace(/"/g, '""');
result = '"' + result + '"';
dataArray.push(result);
}
return dataArray.join(',') + '\r\n';
}
//https://stackoverflow.com/a/6491621
function findbystring(o, s) {
s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
s = s.replace(/^\./, ''); // strip a leading dot
var a = s.split('.');
for (var i = 0, n = a.length; i < n; ++i) {
var k = a[i];
if (k in o) {
o = o[k];
} else {
return;
}
}
return o;
}
function pushUnique(arr, item) {
if (item != "" && !arr.includes(item))
arr.push(item);
}
function getLabels(name, item, labels) {
if (typeof item == 'object') {
for (var index in item) {
thisname = ""
if (name != "") thisname = name + ".";
thisname += index;
getLabels(thisname, item[index], labels);
}
} else {
pushUnique(labels, name);
}
}
function ConvertToCSV(objArray) {
var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
var str = '';
var labels = [];
for (var i = 0; i < array.length; i++) {
getLabels("", array[i], labels);
}
str += objectToCSVRow(labels);
for (var i = 0; i < array.length; i++) {
var line = [];
for (var label in labels) {
line.push(findbystring(array[i], labels[label]));
}
str += objectToCSVRow(line);
}
return str;
}
// Example
$(document).ready(function() {
// Create Object
var items = [{
name: "Item 1",
color: "Green",
sizerange: {
max: "X-Large",
min: "X-Small"
}
},
{
name: "Item 2",
color: "Green",
size: "X-Large",
owner: {
name: "Bill",
address: {
line1: "1 test st",
suburb: "testville"
}
}
},
{
name: "Item 3",
color: "Green",
sizes: ["X-Large", "Large", "Small"]
}
];
// Convert Object to JSON
var jsonObject = JSON.stringify(items, null, 2);
// Display JSON
$('#json').text(jsonObject);
// Convert JSON to CSV & Display CSV
$('#csv').text(ConvertToCSV(jsonObject));
});
<html>
<head>
<title>Demo - Covnert JSON to CSV</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript" src="https://github.com/douglascrockford/JSON-js/raw/master/json2.js"></script>
<script type="text/javascript">
</script>
</head>
<body>
<h1>
JSON</h1>
<pre id="json"></pre>
<h1>
CSV</h1>
<pre id="csv"></pre>
</body>
</html>
Sometimes objects have different lengths. So I ran into the same problem as Kyle Pennell. But instead of sorting the array we simply traverse over it and pick the longest. Time complexity is reduced to O(n), compared to O(n log(n)) when sorting first.
I started with the code from Christian Landgren's updated ES6 (2016) version.
json2csv(json) {
// you can skip this step if your input is a proper array anyways:
const simpleArray = JSON.parse(json)
// in array look for the object with most keys to use as header
const header = simpleArray.map((x) => Object.keys(x))
.reduce((acc, cur) => (acc.length > cur.length ? acc : cur), []);
// specify how you want to handle null values here
const replacer = (key, value) => (
value === undefined || value === null ? '' : value);
let csv = simpleArray.map((row) => header.map(
(fieldName) => JSON.stringify(row[fieldName], replacer)).join(','));
csv = [header.join(','), ...csv];
return csv.join('\r\n');
}
An adaption from praneybehl answer to work with nested objects and tab separator
function ConvertToCSV(objArray) {
let array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
if(!Array.isArray(array))
array = [array];
let str = '';
for (let i = 0; i < array.length; i++) {
let line = '';
for (let index in array[i]) {
if (line != '') line += ','
const item = array[i][index];
line += (typeof item === 'object' && item !== null ? ConvertToCSV(item) : item);
}
str += line + '\r\n';
}
do{
str = str.replace(',','\t').replace('\t\t', '\t');
}while(str.includes(',') || str.includes('\t\t'));
return str.replace(/(\r\n|\n|\r)/gm, ""); //removing line breaks: https://stackoverflow.com/a/10805198/4508758
}
Here is the latest answer using a well optimized and nice csv plugin:
(The code may not work on stackoverflow here but will work in your project as i have tested it myself)
Using jquery and jquery.csv library (Very well optimized and perfectly escapes everything)
https://github.com/typeiii/jquery-csv
// Create an array of objects
const data = [
{ name: "Item 1", color: "Green", size: "X-Large" },
{ name: "Item 2", color: "Green", size: "X-Large" },
{ name: "Item 3", color: "Green", size: "X-Large" }
];
// Convert to csv
const csv = $.csv.fromObjects(data);
// Download file as csv function
const downloadBlobAsFile = function(csv, filename){
var downloadLink = document.createElement("a");
var blob = new Blob([csv], { type: 'text/csv' });
var url = URL.createObjectURL(blob);
downloadLink.href = url;
downloadLink.download = filename;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}
// Download csv file
downloadBlobAsFile(csv, 'filename.csv');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdn.tutorialjinni.com/jquery-csv/1.0.11/jquery.csv.min.js"></script>
Heres a way to do it for dynamically deep objects in a object oriented way for the newer js versions. you might have to change the seperatortype after region.
private ConvertToCSV(objArray) {
let rows = typeof objArray !== "object" ? JSON.parse(objArray) : objArray;
let header = "";
Object.keys(rows[0]).map(pr => (header += pr + ";"));
let str = "";
rows.forEach(row => {
let line = "";
let columns =
typeof row !== "object" ? JSON.parse(row) : Object.values(row);
columns.forEach(column => {
if (line !== "") {
line += ";";
}
if (typeof column === "object") {
line += JSON.stringify(column);
} else {
line += column;
}
});
str += line + "\r\n";
});
return header + "\r\n" + str;
}
Personally I would use d3-dsv library to do this. Why to reinvent the wheel?
import { csvFormat } from 'd3-dsv';
/**
* Based on input data convert it to csv formatted string
* #param (Array) columnsToBeIncluded array of column names (strings)
* which needs to be included in the formated csv
* #param {Array} input array of object which need to be transformed to string
*/
export function convertDataToCSVFormatString(input, columnsToBeIncluded = []) {
if (columnsToBeIncluded.length === 0) {
return csvFormat(input);
}
return csvFormat(input, columnsToBeIncluded);
}
With tree-shaking you can just import that particular function from d3-dsv library
I wanted to riff off #Christian Landgren's answer above. I was confused why my CSV file only had 3 columns/headers. This was because the first element in my json only had 3 keys. So you need to be careful with the const header = Object.keys(json[0]) line. It's assuming that the first element in the array is representative. I had messy JSON that with some objects having more or less.
So I added an array.sort to this which will order the JSON by number of keys. So that way your CSV file will have the max number of columns.
This is also a function that you can use in your code. Just feed it JSON!
function convertJSONtocsv(json) {
if (json.length === 0) {
return;
}
json.sort(function(a,b){
return Object.keys(b).length - Object.keys(a).length;
});
const replacer = (key, value) => value === null ? '' : value // specify how you want to handle null values here
const header = Object.keys(json[0])
let csv = json.map(row => header.map(fieldName => JSON.stringify(row[fieldName], replacer)).join(','))
csv.unshift(header.join(','))
csv = csv.join('\r\n')
fs.writeFileSync('awesome.csv', csv)
}
Here's my simple version of converting an array of objects ito CSV (assuming those objects all share the same attributes):
var csv = []
if (items.length) {
var keys = Object.keys(items[0])
csv.push(keys.join(','))
items.forEach(item => {
let vals = keys.map(key => item[key] || '')
csv.push(vals.join(','))
})
}
csv = csv.join('\n')
Write Csv.
function writeToCsv(dataToWrite, callback) {
var dataToWrite;
var fs = require('fs');
dataToWrite = convertToCSV(dataToWrite);
fs.writeFile('assets/distanceInfo.csv', dataToWrite, 'utf8', function (err) {
if (err) {
console.log('Some error occured - file either not saved or corrupted file saved.');
} else{
console.log('It\'s saved!');
}
callback("data_saved | assets/distanceInfo.csv")
});
}
function convertToCSV(objArray) {
var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
var str = '';
for (var i = 0; i < array.length; i++) {
var line = '';
for (var index in array[i]) {
if (line != '') line += ','
line += array[i][index];
}
str += line + '\r\n';
}
return str;
}
Funny nothing complete nor working here (IE nor node.js). Answer on similar question, a bit structured JSON (suppose no need to copy it again), also demo snippet included.
JSON To CSV conversion (JavaScript) : How to properly format CSV conversion
Hope not only single type convertor, also on my Github (mentioned in profile) is similar used to analyze unknow JSON structure.
I am author of code in this answer and all code on my Github (except some projects started as fork/+translation).
A simple function to convert nested JS objects (without arrays) to csv format in an inline and formatted style ..
const Obj2Csv = (data, level = 0) => (
Object.keys(data).reduce((prevValue, currValue) => {
if (typeof data[currValue] === 'object' && !Array.isArray(data[currValue])) {
// format a deeper object
const formattedObjProp = `${prevValue}${','.repeat(level)}${currValue}\r\n`;
level++;
const formattedObj = `${formattedObjProp}${Obj2Csv(data[currValue], level)}`;
level--;
return formattedObj;
}
return `${prevValue}${','.repeat(level)}${currValue},${data[currValue]}\r\n`
}, '')
)
const obj = {
baz: {
foo: {
bar: 5
}
}
};
console.log(Obj2Csv(obj))
export function convertJsontoCSV(jsonData, fileName = "sheet.csv") {
/* *This function converts the jsonData into CSV and then downloads it
*the jsonData is supposed to be array of Objects with similar structure
*the fileName should be provided otherwise it will set the default name as below.
*/
/* The code that converts the jsonData into CSV data*/
let json = jsonData
let fields = Object.keys(json[0])
let replacer = function (key, value) { return value === null ? '' : value }
let csv = json.map(function (row) {
return fields.map(function (fieldName) {
return JSON.stringify(row[fieldName], replacer)
}).join(',')
})
csv.unshift(fields.join(','))
csv = csv.join('\r\n');
/* The code that downloads the CSD data as a .csv file*/
let downloadLink = document.createElement("a");
let blob = new Blob(["\ufeff", csv]);
let url = URL.createObjectURL(blob);
downloadLink.href = url;
downloadLink.download = fileName; //Name the file here
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}
The following function has been written with help from the answers above.
Here is what I have done. I've used this function when I have an array of objects in JSON format. First of all, there are a lot of flavors of csv. So I've approached it this way, and my files seem to open up ok in spreadsheet editors. Adapted from RFC 4180 and MIME standards/wikipedia:
Each record should contain the same number of comma-separated fields.
Any field may be quoted (with double quotes).
If double-quotes are used to enclose fields, then a double-quote in a field must be represented by two double-quote characters. (internal " is escaped with "")
some type of carriage return/line feed
I know there are more complicated faster, and more elegant ways, but here is a readable and hopefully understandable function that will take in JSON and return a csv with those constraints.
Here is a rundown of the function, again not optimized for performance as it uses 2 passes.
Run through every array entry and get and collect all the key names on the first pass.
Make a header based on the key names
On a second pass, go through the entries and write the values using the keys.
If its undefined, don't write "undefined", instead write "".
If its not a string, stringify it. (After all its valid JSON, so just use JSON.stringify.) This will take care of objects, arrays, null, boolean, etc.
If it is a string do nothing of course.
Now replace any interior " with "".
Now wrap each entry in an outer pair of "" separated by commas with no spaces.
Don't forget the new line \n between lines.
The result is a string that should open in most spreadsheets easily.
function makeCSVFromJSON(myJSON) {
//FIRST PASS// -- collect field names for csv table
let fieldNamesArray = [];
for (arrayEntry of myJSON) {
for (const field in arrayEntry) {
if (!fieldNamesArray.includes(field)) {
fieldNamesArray.push(field)
};
}
}
//make header with field names
let csvString = "";
for (field of fieldNamesArray) {
field = field.replaceAll('"', '""'); //any interior " needs to be replaced with ""
csvString += "\"" + field + "\","; //surround each field with quotes
}
csvString = csvString.slice(0, -1) + "\n"; //remove last comma and add new line
//SECOND PASS -- fill in table using field names/keys
for (arrayEntry of myJSON) {
for (field of fieldNamesArray) {
let csvEntry = arrayEntry[field];
if (csvEntry === undefined) { //if undefined set to empty string ""
csvEntry = "";
} else if (typeof(csvEntry) != "string") { //if its not a string make it a string
csvEntry = JSON.stringify(csvEntry);
}
csvEntry = csvEntry.replaceAll('"', '""');
csvString += "\"" + csvEntry + "\"" + ","
}
csvString = csvString.slice(0, -1) + "\n";
}
return csvString;
}
Here is my solution, as no other one here has support for dynamic columns (they use the first row to determine the columns):
function toCsv(summary, replacer = (_, v) => v) {
let csv = [[]]
for (const data of summary) {
let row = []
for (const column in data) {
let columnIndex = csv[0].indexOf(column)
if (columnIndex === -1) {
columnIndex = csv[0].length
csv[0].push(column)
}
row[columnIndex] = replacer(column, data[column])
}
csv.push(row.join(","))
}
csv[0] = csv[0].join(",")
return csv.join("\r\n")
}
You can pass a replacer function if you need to convert certain column' value.
function jsonToCsv(data) {
return (
Object.keys(data[0]).join(",") +
"\n" +
data.map((d) => Object.values(d).join(",")).join("\n")
);
}
This is of course not for nested json array. But to map json into csv, I would recommend first to simplify nested json array.
Typescript simple method taking into account:
✅ Keys/Values can have " inside it
✅ Keys/Values can have , inside it
✅ Values can have array or objects inside it
Playground Link
const arrayToCSV = (myJSON: any[]) => {
const escapeValue = (value: any) => {
const content = (() => {
if (!value) {
return "";
}
if (typeof value === "object") {
return JSON.stringify(value).replace(/"/g, '""')
}
return value.toString();
})()
return `"${content}"`
};
const fieldNamesArray: string[] = [...new Set(
myJSON.reduce((acc, arrayEntry) => {
return [...acc, ...Object.keys(arrayEntry)];
}, [])
)] as any[];
const header = fieldNamesArray.map(escapeValue).join(',');
const rows = myJSON.map(arrayEntry => {
return fieldNamesArray.map((field) => {
return escapeValue(arrayEntry[field]);
}).join(',');
}).join('\n');
return `${header}\n${rows}`;
};
Hope that helps :D

Accessing data in Google Maps PHP with jQuery

I'm having trouble correctly accessing data in Google Maps API php.
Heres what example data looks in php:
{"destination_addresses":["Destination address"],"origin_addresses":["Origin address"],"rows":[{"elements":[{"distance":{"text":"3.3 km","value":3314},"duration":{"text":"6 mins","value":334},"status":"OK"}]}],"status":"OK"}
Heres my .js:
$(function(){
$("#button").click(function(){
var start = $("#start").val(); //gets start and end values from input fields, and passes them to .php which is not visible here.
var end = $("#end").val();
$.ajax({url: "googlemaps.php",
method: "GET",
data : { "start" : start, "end" : end },
success: function(result) {
print(result);
},
error: function(xhr){
alert("Error: " + xhr.status + " " + xhr.statusText);
}
});
});
});
function print(result){
var length = "";
for(var i = 0;i < result.rows.length;i++){
length += result.rows[i].text+ "<br/>";
$("#div").html(length);
}}
It should calculate the distance between two addresses, and it currently returns unidentified (which is ok), since
length += result.rows[i].text+ "<br/>";
is not correct. I have no idea how to access value "text":"3.3 km", or it's equivalent in my code. I know it is an object inside "distance", which is an array item of "elements", which is an array item of "rows".
Its structured like:
rows[0].elements[0].distance.text
You might not need the loop, but if you were to use it you would do something like.
for (var i = 0;i < result.rows.length; i++) {
for (var k = 0;k < result.rows[i].elements.length; k++) {
length += result.rows[i].elements[k].distance.text + "<br/>";
}
}
$("#div").html(length);
If your array is result, then you can access the distance by using this:
var distance = result['rows'][0]['elements'][0]['distance']['text'];

JavaScript - How can I use the print function to output 2 values that are stored in an array when those values are the same?

var students = [
{
name : "Dave",
track : "Front End Development",
achievement: 158,
points: 14703
},
{
name : "Jody",
track : "iOS Development with swift",
achievement: 133,
points: 16303
},
{
name : "Dave",
track : "PHP Development",
achievement: 55,
points: 2023
},
{
name : "Shawdesh",
track : "Learn Wordpress",
achievement: 40,
points: 1950
},
{
name : "Liton",
track : "Rails Development",
achievement: 98,
points: 450
}
]
var student;
var message = [];
var search;
function print(message) {
document.getElementById('output').innerHTML = message;
}
function getStudentReport(student) {
var report = "<h3> Student: " + student.name + "</h3>";
report += "<p>Track: "+ student.track + "</p>";
report += "<p>achievement: "+ student.achievement + "</p>";
report += "<p>Points: "+ student.points + "</p>";
return report;
}
while(true) {
search = prompt("Search the student recoards: type a name [Jody] or (type quit to exit.)");
if (search == null || search.toLowerCase() == 'quit') {
break;
}
for (var i = 0; i < students.length; i += 1) {
student = students[i];
if (student.name.toLowerCase() === search.toLowerCase()) {
message.push(getStudentReport(student));
}
}
for (var j = 0; j < message.length; j += 1) {
document.write(message[j]);
}
}
When the prompt function runs, if I write #Dave the message array stores 2 value because in #students Array the Dave name uses two times.
But when I print this array by print function it only prints the last value. But when I print it by document.write it prints 2 value.
So, now my question is: How can I print 2 values that are stored in a message array using my #print function?
Sure it will add just the last message since you're using affection = that will override the content, instea use += to append the new message to the old content, like :
function print(message) {
document.getElementById('output').innerHTML += message;
}
Hope this helps.

how to check whether NAN is present in json string or not

suppose i have below function, which is getting jsonData in the form of jason, i validate the var jsonData to check for NaN ?
function save() {
var jsonData = getEnteredValue();
$.ajax({
type : 'POST',
url : 'saveSalesForecast.json',
data : 'jsonPostData=' + jsonData,
success : function() { //alert("success");
}
});
}
i only know how to replace NAN but don know how to check for NAN!
jsonData = JSON.parse(jsonData.replace(/\bNaN\b/g, "null"));
here is remaining function:(any field values can be string,numbers but it should not be NAN
function getEnteredValue() {
var rowIds = $("#salesForecastGrid").jqGrid('getDataIDs');
var ids=[];
var jsonPostData = "[";
for ( var i = 0; i <= rowIds.length-1; i++) {
$("#salesForecastGrid").jqGrid('editCell', i, 2, false);
var forecastedSales = parseFloat($("#salesForecastGrid")
.jqGrid('getCell', rowIds[i], 'forecastedSales'));
if (!((forecastedSales == "") || isNaN(forecastedSales) || (forecastedSales ==0))) {
if (ids.indexOf(rowIds[i])==-1){
ids.push(rowIds[i]);
}
}
}
for ( var i = 0; i <= ids.length-1; i++) {
var forecastedSales = parseFloat($("#salesForecastGrid")
.jqGrid('getCell', ids[i], 'forecastedSales'));
var id = $("#salesForecastGrid").jqGrid('getCell', ids[i],
'id');
var date = $("#salesForecastGrid").jqGrid('getCell',
ids[i], 'day');
if (id < 0) {
id = 0;
}
var record = "{" + "id:" + id + "," + "date:" + date + ","
+ "forecastedSales:" + forecastedSales + "}";
jsonPostData = jsonPostData + record;
if (i != ids.length) {
jsonPostData = jsonPostData + ",";
}
}
jsonPostData += "]";
return jsonPostData;
}
Json Data like:
"[{id:68447,date:04-17-2014,forecastedSales:8420.42},{id:68448,date:04-18-2014,‌​forecastedSales:9912.68},]"
Your problem is that you are creating the JSON manually, and thus end up with invalid JSON. Do yourself a favor and use JSON.stringify:
function getEnteredValue() {
var rowIds = $("#salesForecastGrid").jqGrid('getDataIDs');
var ids=[];
var data = [];
// ...
for ( var i = 0; i < ids.length; i++) {
// ...
data.push(
{id: id, date: date, forecastedSales: forecastedSales}
);
}
return JSON.stringify(data);
}
Since NaN is not a valid value in JSON, it will automatically be converted to null. Example:
> JSON.stringify({a: NaN});
"{"a":null}"
For more info see Using native JSON.
NaN is not acceptable in JSON. JSON specification does not support NaN as a value. Even when javascript object has NaN value, it will be converted to null when you serialise to JSON format.
First of all, JSON is not an Javascript Object. JSON is general format which can be understand by all languages.

How do I iterate over a JSON structure? [duplicate]

This question already has answers here:
Loop (for each) over an array in JavaScript
(40 answers)
Closed 5 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
I have the following JSON structure:
[{ "id":"10", "class": "child-of-9" }, { "id": "11", "classd": "child-of-10" }]
How do I iterate over it using JavaScript?
var arr = [ {"id":"10", "class": "child-of-9"}, {"id":"11", "class": "child-of-10"}];
for (var i = 0; i < arr.length; i++){
document.write("<br><br>array index: " + i);
var obj = arr[i];
for (var key in obj){
var value = obj[key];
document.write("<br> - " + key + ": " + value);
}
}
note: the for-in method is cool for simple objects. Not very smart to use with DOM object.
Taken from jQuery docs:
var arr = [ "one", "two", "three", "four", "five" ];
var obj = { one:1, two:2, three:3, four:4, five:5 };
jQuery.each(arr, function() {
$("#" + this).text("My id is " + this + ".");
return (this != "four"); // will stop running to skip "five"
});
jQuery.each(obj, function(i, val) {
$("#" + i).append(document.createTextNode(" - " + val));
});
Use for...of:
var mycars = [{name:'Susita'}, {name:'BMW'}];
for (var car of mycars)
{
document.write(car.name + "<br />");
}
Result:
Susita
BMW
Please let me know if it is not easy:
var jsonObject = {
name: 'Amit Kumar',
Age: '27'
};
for (var prop in jsonObject) {
alert("Key:" + prop);
alert("Value:" + jsonObject[prop]);
}
If this is your dataArray:
var dataArray = [{"id":28,"class":"Sweden"}, {"id":56,"class":"USA"}, {"id":89,"class":"England"}];
then:
$(jQuery.parseJSON(JSON.stringify(dataArray))).each(function() {
var ID = this.id;
var CLASS = this.class;
});
Copied and pasted from http://www.w3schools.com, there is no need for the JQuery overhead.
var person = {fname:"John", lname:"Doe", age:25};
var text = "";
var x;
for (x in person) {
text += person[x];
}
RESULT: John Doe 25
mootools example:
var ret = JSON.decode(jsonstr);
ret.each(function(item){
alert(item.id+'_'+item.classd);
});
You can use a mini library like objx - http://objx.googlecode.com/
You can write code like this:
var data = [ {"id":"10", "class": "child-of-9"},
{"id":"11", "class": "child-of-10"}];
// alert all IDs
objx(data).each(function(item) { alert(item.id) });
// get all IDs into a new array
var ids = objx(data).collect("id").obj();
// group by class
var grouped = objx(data).group(function(item){ return item.class; }).obj()
There are more 'plugins' available to let you handle data like this, see http://code.google.com/p/objx-plugins/wiki/PluginLibrary
With nested objects, it can be retrieve as by recursive function:
function inside(events)
{
for (i in events) {
if (typeof events[i] === 'object')
inside(events[i]);
else
alert(events[i]);
}
}
inside(events);
where as events is json object.
Marquis Wang's may well be the best answer when using jQuery.
Here is something quite similar in pure JavaScript, using JavaScript's forEach method. forEach takes a function as an argument. That function will then be called for each item in the array, with said item as the argument.
Short and easy:
var results = [ {"id":"10", "class": "child-of-9"}, {"id":"11", "classd": "child-of-10"} ];
results.forEach(function(item) {
console.log(item);
});
this is a pure commented JavaScript example.
<script language="JavaScript" type="text/javascript">
function iterate_json(){
// Create our XMLHttpRequest object
var hr = new XMLHttpRequest();
// Create some variables we need to send to our PHP file
hr.open("GET", "json-note.php", true);//this is your php file containing json
hr.setRequestHeader("Content-type", "application/json", true);
// Access the onreadystatechange event for the XMLHttpRequest object
hr.onreadystatechange = function() {
if(hr.readyState == 4 && hr.status == 200) {
var data = JSON.parse(hr.responseText);
var results = document.getElementById("myDiv");//myDiv is the div id
for (var obj in data){
results.innerHTML += data[obj].id+ "is"+data[obj].class + "<br/>";
}
}
}
hr.send(null);
}
</script>
<script language="JavaScript" type="text/javascript">iterate_json();</script>// call function here
var jsonString = `{
"schema": {
"title": "User Feedback",
"description": "so",
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
},
"options": {
"form": {
"attributes": {},
"buttons": {
"submit": {
"title": "It",
"click": "function(){alert('hello');}"
}
}
}
}
}`;
var jsonData = JSON.parse(jsonString);
function Iterate(data)
{
jQuery.each(data, function (index, value) {
if (typeof value == 'object') {
alert("Object " + index);
Iterate(value);
}
else {
alert(index + " : " + value);
}
});
}
Iterate(jsonData);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Another solution to navigate through the JSON document is JSONiq (implemented in the Zorba engine), where you can write something like this:
let $doc := [
{"id":"10", "class": "child-of-9"},
{"id":"11", "class": "child-of-10"}
]
for $entry in members($doc) (: binds $entry to each object in turn :)
return $entry.class (: gets the value associated with "class" :)
You can run it on http://public.rumbledb.org:9090/public.html

Categories