Converting CSV to JSON using JavaScript - javascript

I'm learning JavaScript and i'm trying to convert a CSV file to a JSON.
The structure of my csv is :
Name
Class
region_count
Coordinates
foto_4.jpeg
soccer
1
"all_points_x":[90,80,77,74,82,89,113,142,146,153,162,174,184,199,220,235,261,280,289,298,298,287,279,276,271,268,265,266,270,270,262,249,236,222,213,188,170,151,114,92],"all_points_y":[145,171,192,211,241,263,291,308,310,301,288,275,265,257,246,244,241,238,241,243,235,223,208,196,176,165,148,134,119,114,109,99,96,93,90,89,89,94,116,146]
foto_4.jpeg
tennis
2
"all_points_x":[394,418,445,456,467,472,469,461,448,436,425,412,402,394,384,383,392],"all_points_y":[276,259,260,266,279,296,313,327,335,341,342,338,334,326,313,294,279]
foto_5.jpeg
basket
1
"all_points_x":[345,373,427,479,509,540,553,549,541,526,490,467,455,447,430,421,411,406,400,394,391,381,368,349,337,327,320,308,301],"all_points_y":[23,11,7,22,44,89,140,182,207,230,261,274,263,260,255,255,255,261,268,273,278,286,279,273,268,258,250,242,237]
the desired json structure is:
{"foto_1jpg.jpg121349":{"filename":"foto_1jpg.jpg","regions":[{"shape_attributes":{"all_points_x":[154,157,230,275,278,218,160,112,113,154],"all_points_y":[461,461,455,495,576,625,625,563,505,463]},"region_attributes":{"name":"tennis"}},{"shape_attributes":{"all_points_x":[446,557,685,795,826,815,738,628,505,422,346,331,354,443],"all_points_y":[230,186,212,321,411,538,641,687,684,632,525,426,331,224]},"region_attributes":{"name":"soccer"}}],"file_attributes":{}},"foto_2.jpg325912":{"filename":"foto_2.jpg","regions":[{"shape_attributes":{"all_points_x":[331,403,518,626,688,734,758,681,594,484,369,314,282,274,329],"all_points_y":[399,340,316,342,380,463,607,736,787,796,745,683,592,503,405]},"region_attributes":{"name":"soccer"}},{"shape_attributes":{"name":"polygon","all_points_x":[972,887,830,802,789,804,857,963,1050,1135,1220,1284,1314,1307,1263,1178,1116,1057,955],"all_points_y":[144,195,261,327,397,484,579,639,660,647,603,524,424,335,238,174,146,140,157]}],"file_attributes":{}},"foto_3.jpg196633":{"filename":"foto_3.jpg","regions":[{"shape_attributes":{"name":"polygon","all_points_x":[65,43,49,107,160,215,290,351,406,431,409,373,334,274,203,150,107,70],"all_points_y":[349,421,503,586,622,630,629,593,537,465,356,313,283,264,256,278,303,346]},"region_attributes":{"name":"soccer"}}],"file_attributes":{}}}
I tried to convert this CSV to JSON with this code
var csv = `,Name,Class,Region_count,Coordinates
0,foto_1jpg.jpg,tennis,1,"""all_points_x"":[154,157,230,275,278,218,160,112,113,154],""all_points_y"":[461,461,455,495,576,625,625,563,505,463]"
1,foto_1jpg.jpg,soccer,2,"""all_points_x"":[446,557,685,795,826,815,738,628,505,422,346,331,354,443],""all_points_y"":[230,186,212,321,411,538,641,687,684,632,525,426,331,224]"
2,foto_1jpg.jpg,basket,3,"""all_points_x"":[941,1065,1161,1310,1438,1497,1509,1471,1382,1279,1124,998,916,874,847,874,938],""all_points_y"":[132,44,26,48,144,266,396,514,628,673,687,631,560,479,328,233,135]"
3,foto_2jpg.jpg,soccer,1,"all_points_x:[331,403,518,626,688,734,758,681,594,484,369,314,282,274,329],""all_points_y"":[399,340,316,342,380,463,607,736,787,796,745,683,592,503,405]"
4,foto_2jpg.jpg,basket,2,"""all_points_x"":[972,887,830,802,789,804,857,963,1050,1135,1220,1284,1314,1307,1263,1178,1116,1057,955],""all_points_y"":[144,195,261,327,397,484,579,639,660,647,603,524,424,335,238,174,146,140,157]"
5,foto_2jpg.jpg,tennis,3,"all_points_x:[1186,1233,1273,1282,1267,1231,1178,1154,1135,1131,1142,1182],""all_points_y"":[921,921,891,845,806,777,775,789,819,859,895,919]"
6,foto_3jpg.jpg,soccer,1,"""all_points_x"":[65,43,49,107,160,215,290,351,406,431,409,373,334,274,203,150,107,70],""all_points_y"":[349,421,503,586,622,630,629,593,537,465,356,313,283,264,256,278,303,346]"
7,foto_3jpg.jpg,basket,2,"""all_points_x"":[523,588,647,739,809,854,871,877,860,845,830,823,816,811,804,802,796,774,765,753,726,712,699,685,682,671,670,666,664,632,601,583,549,515,496,469,446,448,467,518],""all_points_y"":[242,203,196,206,247,307,361,436,491,509,515,521,530,537,549,561,572,583,583,562,550,547,554,557,571,578,591,601,620,615,612,608,588,552,532,496,428,370,319,244]"
8,foto_3jpg.jpg,tennis,3,"all_points_x:[838,881,901,917,912,888,869,845,821,804,792,791,813],""all_points_y"":[544,544,569,600,627,646,654,654,651,634,601,578,552]"`;
var map = {};
var rows = csv.split(/\n/g);
var keys = rows.shift().split(",");
rows.forEach(raw_row=>{
var row = {};
var row_key;
var columns = raw_row.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
columns.forEach((column, index)=>{
var key = keys[index];
if(!key) return;
if(key === 'Name'){
row_key = column;
return;
}
if(key === "Coordinates"){
column = column.replace(/""/g, '"');
column = column.substring(1, column.length-1);
column = column.replace(/([a-zA-Z_]+):/g, `"$1":`);
try{ column = JSON.parse(`{${column}}`); }catch(e){}
}
row[key] = column;
});
map[row_key] = row;
});
console.log(map);
the JSON create is this:
{"foto_1jpg.jpg":{"Class":"basket","region_count":"3","Coordinates":{"all_points_x":[941,1065,1161,1310,1438,1497,1509,1471,1382,1279,1124,998,916,874,847,874,938],"all_points_y":[132,44,26,48,144,266,396,514,628,673,687,631,560,479,328,233,135]}},"foto_2jpg.jpg":{"Class":"tennis","region_count":"3","Coordinates":{"all_points_x":[1186,1233,1273,1282,1267,1231,1178,1154,1135,1131,1142,1182],"all_points_y":[921,921,891,845,806,777,775,789,819,859,895,919]}},"foto_3jpg.jpg":{"Class":"tennis","region_count":"3","Coordinates":{"all_points_x":[838,881,901,917,912,888,869,845,821,804,792,791,813],"all_points_y":[544,544,569,600,627,646,654,654,651,634,601,578,552]}}}
With my code I can't iterate for all the polygons contained in one picture and I can't add region key (example region) that contains other keys
How can I reach my desired output?

Your initial approach looks pretty good. We just need some more modifications to the data you generated. Instead of directly mapping each row to JSON, first keep data in the array as a line item, and then build the JSON data as follows.
var csv = `,Name,Class,Region_count,Coordinates
0,foto_1jpg.jpg,tennis,1,"""all_points_x"":[154,157,230,275,278,218,160,112,113,154],""all_points_y"":[461,461,455,495,576,625,625,563,505,463]"
1,foto_1jpg.jpg,soccer,2,"""all_points_x"":[446,557,685,795,826,815,738,628,505,422,346,331,354,443],""all_points_y"":[230,186,212,321,411,538,641,687,684,632,525,426,331,224]"
2,foto_1jpg.jpg,basket,3,"""all_points_x"":[941,1065,1161,1310,1438,1497,1509,1471,1382,1279,1124,998,916,874,847,874,938],""all_points_y"":[132,44,26,48,144,266,396,514,628,673,687,631,560,479,328,233,135]"
3,foto_2jpg.jpg,soccer,1,"all_points_x:[331,403,518,626,688,734,758,681,594,484,369,314,282,274,329],""all_points_y"":[399,340,316,342,380,463,607,736,787,796,745,683,592,503,405]"
4,foto_2jpg.jpg,basket,2,"""all_points_x"":[972,887,830,802,789,804,857,963,1050,1135,1220,1284,1314,1307,1263,1178,1116,1057,955],""all_points_y"":[144,195,261,327,397,484,579,639,660,647,603,524,424,335,238,174,146,140,157]"
5,foto_2jpg.jpg,tennis,3,"all_points_x:[1186,1233,1273,1282,1267,1231,1178,1154,1135,1131,1142,1182],""all_points_y"":[921,921,891,845,806,777,775,789,819,859,895,919]"
6,foto_3jpg.jpg,soccer,1,"""all_points_x"":[65,43,49,107,160,215,290,351,406,431,409,373,334,274,203,150,107,70],""all_points_y"":[349,421,503,586,622,630,629,593,537,465,356,313,283,264,256,278,303,346]"
7,foto_3jpg.jpg,basket,2,"""all_points_x"":[523,588,647,739,809,854,871,877,860,845,830,823,816,811,804,802,796,774,765,753,726,712,699,685,682,671,670,666,664,632,601,583,549,515,496,469,446,448,467,518],""all_points_y"":[242,203,196,206,247,307,361,436,491,509,515,521,530,537,549,561,572,583,583,562,550,547,554,557,571,578,591,601,620,615,612,608,588,552,532,496,428,370,319,244]"
8,foto_3jpg.jpg,tennis,3,"all_points_x:[838,881,901,917,912,888,869,845,821,804,792,791,813],""all_points_y"":[544,544,569,600,627,646,654,654,651,634,601,578,552]"`;
var items = []
var rows = csv.split(/\n/g);
var keys = rows.shift().split(",");
rows.forEach(raw_row => {
var row = {};
var columns = raw_row.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
columns.forEach((column, index)=>{
var key = keys[index];
if(!key) return;
if(key === "Coordinates"){
column = column.replace(/""/g, '"');
column = column.substring(1, column.length-1);
column = column.replace(/([a-zA-Z_]+):/g, `"$1":`);
try{ column = JSON.parse(`{${column}}`); }catch(e){}
}
row[key] = column;
});
items.push(row);
});
const map = {}
for (const item of items) {
if (!map[item['Name']]) {
map[item['Name']] = {
'filename': item['Name'],
'regions': [],
'file_attributes': {}
}
}
map[item['Name']].regions.push(
{
"shape_attributes": item['Coordinates'],
"region_attributes": { "name": item['Class'] }
}
)
}
console.log(map)

Related

Faster way to collect data from JSON than looping in spreadsheet

I am learning Javascript and this is my first time working with Google Sheets Apps Script. What I am doing is taking a large JSON file and importing it into my sheet. After that I am populating a few hundred properties based on the key:value found in the JSON.
This is how it kinda works right now:
Go to first column and first row of my sheet.
Get the name (property name).
Search the JSON for the key and then grab the value.
Update a neighbor cell with the value found in the JSON.
Right now it all works the only issue is it seems to be pretty slow. It takes about .5-1 second per lookup and when I have 200+ properties it just seems slow. This might just be a limitation or it might be my logic.
My sheet can be found here: https://docs.google.com/spreadsheets/d/1tt3eh1RjL_CbUIaPzj10DbocgyDC0iNRIba2B4YTGgg/edit#gid=0
My function that does everything:
function parse() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getRange(2,1);
var range1 = sheet.getRange("A2");
var cell = range.getCell(1, 1);
var event_line = cell.getValue();
var tmp = event_line.split(". ");
var col_number = tmp[0];
var event_name = tmp[1];
event_json = get_json_from_cell(col_number);
const obj = JSON.parse(event_json);
var traits = obj.context.traits;
var properties = obj.properties;
//Get the range for the section where properties are
var traits_range = sheet.getRange("contextTraits");
var allprop = sheet.getRange("testAll");
var alllen = allprop.getNumRows();
var length = traits_range.getNumRows();
for (var i = 1; i < length; i++) {
var cell = traits_range.getCell(i, 1);
var req = traits_range.getCell(i, 4).getValue();
var trait = cell.getValue();
var result = traits[trait];
var result_cell = traits_range.getCell(i, 3);
if (result == undefined) {
if (req == "y"){
result = "MISSING REQ";
result_cell.setBackground("red");
} else {
result = "MISSING";
result_cell.setBackground("green");
}
} else {
result_cell.setBackground("blue");
}
result_cell.setValue(result);
Logger.log(result);
}
for (var i = 1; i < alllen; i++) {
var cell = allprop.getCell(i,1);
var req = allprop.getCell(i, 4).getValue();
var prop = cell.getValue();
var result = properties[prop];
var result_cell = allprop.getCell(i, 3);
if (result == undefined) {
if (req == "y"){
result = "MISSING REQ";
result_cell.setBackground("red");
} else {
result = "MISSING";
result_cell.setBackground("green");
}
} else {
result_cell.setBackground("blue");
}
result_cell.setValue(result);
}
Logger.log(result);
}

setValues from JSON array to spreadsheet

I'm stuck trying to copy the values from my JSON scraping script to spreadsheet.
Does anyone know how to do that?
I'm stuck trying to know how to get the "longname" values to the memory and then using setValue once at the end.
I need to paste all the values here at the column B.
First I'm trying to resolve a single column, later I will need to paste a multi dimensional array to multiple columns. But that's only if I solve this.
Just a detail, on columnWithTickers I used only a range of 5 rows for testing purposes. Later I will use a dynamic value.
Code:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var page1 = ss.getSheetByName("pag1");
let columnWithTickers = page1.getRange(2, 1, 5).getValues();
let targetColumn = page1.getRange(2, 2);
function printValuesFromJSON() {
if (!Array.isArray(columnWithTickers)) {
columnWithTickers = [[columnWithTickers]]
}
return columnWithTickers.map(tickers => {
try {
values = tickers[0].toString().split(",");
let url = `https://finance.yahoo.com/quote/${values}.SA/key-statistics?p=${values}.SA`;
let source = UrlFetchApp.fetch(url).getContentText()
let jsonString = source.match(/root.App.main = ([\s\S\w]+?);\n/)
if (!jsonString || jsonString.length == 1) return;
let data = JSON.parse(jsonString[1].trim());
let longname = data.context.dispatcher.stores.QuoteSummaryStore.price.longName.split();
/*let resultados = longname.map(vetor =>{
return ativosResultados = vetor[0].toString();
})*/
}
catch (error) {
return "N/A"
}
}
)
}
You can try the below function:
function attDiarios(){
var result = intervaloTickers.map(tickersAtuais =>
{
ativosFinais = tickersAtuais[0].toString().split(" ")
let url = `https://finance.yahoo.com/quote/${ativosFinais}.SA/key-statistics?p=${ativosFinais}.SA`;
let source = UrlFetchApp.fetch(url).getContentText()
let jsonString = source.match(/root.App.main = ([\s\S\w]+?);\n/)
if (!jsonString || jsonString.length == 1) return null;
let data = JSON.parse(jsonString[1].trim());
try{
var longNameValue = data.context.dispatcher.stores.QuoteSummaryStore.price.longName;
}
catch(err){
var longNameValue = 'N/A';
}
return [[longNameValue]]
}
)
sImport.getRange(5, 2, result.length, result[0].length).setValues(result);
}

Parse Excel file and create a hash structure(key/value)

I have an Excel file with the following template.
Name, Surname, Class
Alex, Smith, B1,
Maria, Smith, B2
The Excel file has multiple sheets with data in different languages.
I want to read from the Excel file and to create a hash structure (key/value) because I want to add later more information in each entry.
I have achieved to set the keys names for each entry but I cannot understand how I can import the values for each entry.
You can see the required format of the structure here:
var arr = [{
"name":{default:"Alex", cellId:"B1"},
"surname":{default:"Smith", cellId:"B2"},
"class":{default: "B1", cellId:"B3"}
},
{
"name":{default:"Maria", cellId:"C1"},
"surname":{default:"Smith", cellId:"C2"},
"class":{default: "B1", cellId:"C3"}
} ]
$("#btn").on("change", function(e) {
e.preventDefault();
var files = e.target.files;
var i, f;
for (i = 0, f = files[i]; i != files.length; ++i) {
var reader = new FileReader();
reader.onload = function(e) {
var data = e.target.result;
var workbook = XLSX.read(data, {
type: "buffer",
blankRows: true,
defval: ' '
});
var sheet_name_list = workbook.SheetNames;
var theQuestionLanguage = sheet_name_list; //english
var theExcelDataArray = [];
var test;
var data = [];
var headers = {};
sheet_name_list.forEach(function(y) {
var worksheet = workbook.Sheets[y];
var headers = {};
var data = [];
for (z in worksheet) {
//parse out the column, row, and value
var col = z.substring(0, 1);
var row = parseInt(z.substring(1));
var value = worksheet[z].v;
//store header names
if (row == 1 && !headers[value]) {
headers[value] = {};
}
console.log(headers);
if ((headers[value]) && (row !== 1)) {
headers[value].default = "value"
console.log("headers");
}
}
//drop those first two rows which are empty
});
};
reader.readAsArrayBuffer(f);
}
});
First of all, Save As your Excel file in CSV format.
After that, go to this website : Let's go. In this website you can add for information in your each entry and convert them into key/value pair.
I hope this this above information will help you.

How to push json keys and json values into two arrays

I have one json file with following structure:
{
"won":3,
"lost":0,
"void":0,
"active":1
}
I've been trying to figure out how to make two arrays in javascript that will contain following information:
var labels = ["won", "lost", "void", "active"];
var data = ["3","0", "0","1"];
But I can't my head around how to do it.
You can use:
var labels = Object.keys(input);
var data = Object.values(input);
However you should check the browsers compatibility:
Object.keys
Object.values
Try this code
var item_list = {
"won":3,
"lost":0,
"void":0,
"active":1
};
var labels = [];
var data = [];
for(var item in item_list){
// console.log(item);
labels.push(item);
data.push(item_list[item]);
}
console.log(labels);
console.log(data);
You can do this too
var mydata = {
"won":3,
"lost":0,
"void":0,
"active":1
};
var first = [],
second = [];
for (var property in mydata) {
if ( ! mydata.hasOwnProperty(property)) {
continue;
}
first.push(property);
second.push(mydata[property]);
}
console.log(first);
console.log(second);
Try This :
var obj = {
"won":3,
"lost":0,
"void":0,
"active":1
}
var keys = new Array();
var values = new Array();
for (var key in obj) {
keys.push(key)
values.push(obj[key]);
}
console.log(keys);
console.log(values);

How to change default var value in javascript on hover over piechart d3JS

I have a global var country = "Scotland"
and I have a method which takes the value in var country and sets it:
function isScottish(grant){
return grant.organisation.Country === country;
}
I have one callback function called ph which is called on hover over piechart.
var ph = function(d,i){
var DOMelement = this;
var fill = DOMelement.getAttribute("fill");
country="England"; // on hover set country to "England"
console.log(fill);
bc1.colour(fill);
bc1.render();
}
I tried like above but I am unable to set the country = "England".
Full Code :
"strict"
//Globals (so that we can inspect easily in the console)
var dataset1 = [];
var country = "Scotland";
var result = [];
var url = "data.json";
d3.json(url, function(error, jsonData) {
if (error) return userUpdate("Failed attepting to load JSON from :" + url);
processData(jsonData);
});
var scottishGrants; //use global so that we can inspect via console
function processData(jsonData){
dataset1 = jsonData;
//console.log(dataset1);
//Flatten database by adding a pointer to a grant's organisation obj
//in each grant obj
dataset1.grants.forEach(function(grant){
grant.organisation = getOrgByID(grant.OrgID);
})
scottishGrants = dataset1.grants.filter(isScottish)
console.log(scottishGrants);
//Of course we could make this more general by
//obtaining a list of countries (output to console)
var countries = {};
dataset1.organisations.forEach(function(org)
{
//Saves list of countries in countries array object as true
countries[org.Country]=true
})
var countryList = [];
//Key = Country and Value = True
//So therefore loop through countries array object and get keys to push in countryList array.
for (var key in countries) countryList.push(key);
console.log(countries);
console.log ("countryList = "+countryList);
//And then using this list to return a table of grants for each country
result = Array.from(
dataset1.grants.reduce((countries, grant) =>
countries.set(grant.organisation.Country,
(countries.get(grant.organisation.Country) || 0) + +grant.Value),
new Map()),
([country, sum]) => ({country,sum})
);
console.log(result);
}
function getOrgByID(ID){
var organisation=dataset1.organisations.find(function(org){
return org.OrgID === ID
})
return organisation
}
function isScottish(grant){
//return grant.organisation.Country === country;
return grant.organisation.Country === country;
}
//Set up a data generator and initialise with 6 values
var dg1 = dataGenerator(6); <!-- Generates the data and is stored in dg1 variable -->
// console.log(sourceDataset1);
//Create rendering objects
//var chart1 = barchart("#chart1DIV");
var bc1 = barchart("#bc1Div")
var pie1 = piechart("#p1")
.height(300)
.width(300);
//Render for the first time
var ph = function(d, i){
var DOMelement = this;
var fill = DOMelement.getAttribute("fill");
//var countryName = DOMelement.getAttribute("Country");
country="England";
console.log(fill);
bc1.colour(fill);
bc1.render();
}
function render(ds){
pie1.loadAndRenderDataset(ds);
rr1 = rawRenderer("#rr1")
.loadAndRender(ds);
layOutData = rawRenderer("#layoutData1")
.loadAndRender(pie1.layoutData());
bc1.loadDataset(scottishGrants)
.colour("red")
.render();
/*
chart1
.loadDataset(dg1.dataset())
.colour("PaleGreen")
.render();*/
}
pie1.pieOverCallback(ph);

Categories

Resources