I want to create a JSON object from the contents of a CSV file. The CSV file is loaded locally via the FileReader API and that seems to work, however I am having trouble structuring the JSON in the desired way.
My code for loading the CSV file looks like this:
<!DOCTYPE html>
<html>
<body>
<p>Select local CSV File:</p>
<input id="csv" type="file">
<output id="out"> input file content</output>
<script>
var fileInput = document.getElementById("csv"),
readFile = function () {
var reader = new FileReader();
reader.onload = function () {
// Display CSV file contents
document.getElementById('out').innerHTML = reader.result;
};
reader.readAsBinaryString(fileInput.files[0]);
};
fileInput.addEventListener('change', readFile);
</script>
</body>>
</html>
The code above allows me to load the contents of the CSV file and display them on the current page. To structure the CSV data into the desired format above I tried the following, however it didn't work to me:
<!DOCTYPE html>
<html>
<body>
<script>
var fileReader = new FileReader();
function getFile(inputFile) {
let file = inputFile.files[0];
fileReader.readAsText(file);
}
function csvJSON(csv){
var lines=csv.split("\n");
var result = [];
var headers=lines[0].split(",");
for(var i=1;i<lines.length;i++){
var obj = {};
var currentline=lines[i].split(",");
for(var j=0;j<headers.length;j++){
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
return JSON.stringify(result); //JSON
}
function readFile(evt) {
let parsed = csvJSON(evt.target.result);
return parsed;
}
</script>
</body>
</html>
How can I acquire my expected JSON object(s)? Any suggestions would be appreciated
One approach to this would be to iterate through your input CSV data on increments of "6" (where 6 represents the number of different bits of data for each student) to capture all student data per CSV row, and then populate an array of structured JSON objects in the desired format like so:
/* Helper function to perform the CSV to JSON transform */
function convertToJson(inputCsv) {
/* Split input string by `,` and clean up each item */
const arrayCsv = inputCsv.split(',').map(s => s.replace(/"/gi, '').trim())
const outputJson = [];
/* Iterate through input csv at increments of 6, to capture entire CSV row
per iteration */
for (let i = 6; i < arrayCsv.length; i += 6) {
/* Extract CSV data for current row, and assign to named variables */
const [date, firstName, middleName, lastName, uin, rsvpStatus] =
arrayCsv.slice(i, i + 6)
/* Populate structured JSON entry for this CSV row */
outputJson.push({
uin,
studentInfo: {
firstName,
middleName,
lastName,
rsvpStatus
}
});
}
return outputJson;
}
/* Input CSV data from your exsiting code */
const csv = `"Timestamp", "Enter First Name:", "Enter Middle Initial",
"Enter Last Name:", "Enter UIN:", "Are you attending the event?",
"2019/02/22 12:41:56 PM CST", "Jonathan", "Samson", "Rowe", "123456789",
"No", "2019/02/22 12:44:56 PM CST", "phil", "Aspilla", "beltran", "123456788",
"Yes"`
const json = convertToJson(csv);
console.log(json);
var csv = '"Timestamp","Enter First Name:","Enter Middle Initial","Enter Last Name:","Enter UIN:","Are you attending the event?"\n"2019/02/22 12:41:56 PM CST","Jonathan","Samson","Rowe","123456789","No"\n"2019/02/22 12:44:56 PM CST","phil","Aspilla","beltran","123456788","Yes"';
var csvJSON = function(csv) {
let vals = csv.split('\n'), ret = [];
for( let i = 1, len = vals.length; i < len; i++ ){
let person = vals[i].split(',');
ret.push({
uin : person[4],
studentInfo : {
firstName : person[1],
middleName : person[2],
lastName : person[3],
rsvpStatus : person[5]
}
});
}
return JSON.stringify(ret);
}
console.log(csvJSON(csv));
This is assuming the structure of the CSV is always the same.
If you are struggling to parse data, you can also use PapaParse, it has a lot of configurations and it's pretty easy to use:
// Parse CSV string
var data = Papa.parse(csv);
See more information at https://www.papaparse.com/demo
Related
I need to select a .csv file in html and manage it with javascript (I need to convert it into JSON), I did something but it doesn't work well.
To select a file in html I did this:
<input id="inputFile" accept=".csv" type="file"> <br>
<br>
<input value="Send" type="button" onclick="showFile()">
<label id="mylabel">
</label>
<script src="../javascript/parseFileScript.js"></script>
and to manage it I did this:
//take a string containing a csv
function csvJSON(csv){
console.log(typeof csv)
var lines=csv.split("\n");
var result = [];
// NOTE: If your columns contain commas in their values, you'll need
// to deal with those before doing the next step
// (you might convert them to &&& or something, then covert them back later)
// jsfiddle showing the issue https://jsfiddle.net/
var headers=lines[0].split(",");
for(var i=1;i<lines.length;i++){
var obj = {};
var currentline=lines[i].split(",");
for(var j=0;j<headers.length;j++){
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
//return result; //JavaScript object
return JSON.stringify(result); //JSON
}
//load the selected file and convert in string
async function getCSV() {
let file = document.getElementById('inputFile').files[0];
console.log(typeof file)
let text = await file.text();
return text;
}
//put the body of the selected file in a label
function showFile() {
let csv = getCSV();
let json = csvJSON(csv);
document.getElementById('mylabel').innerHTML = json;
}
The error I get is Uncaught TypeError: csv.split is not a function, so I check for the type of csv in the function csvJSON and for the type of file in getCSV and in both cases the console tells me that the type is object.
Can someone explain to me where I'm wrong and how to solve the problem, please?
I'm trying to read and parse an excel file and create a JavaScript array object with the data.
The excel file will look like:
AA11 AA22 AN65
AB11 AB22 AN64
...
And I want the JavaScript array to look like:
[[AA11, AA22, AN65], [AB11, AB22, AN64],...]
So far I have the following code:
<input type="file" id="input" accept=".xls,.xlsx,.ods" />
<a id="result"></a>
<script type="text/javascript">
$("#input").on("change", function(e) {
var file = e.target.files[0];
if (!file) return;
var FR = new FileReader();
function byDocument(e) {
var data = new Uint8Array(e.target.result);
var workbook = XLSX.read(data, { type: "array" });
var firstSheet = workbook.Sheets[workbook.SheetNames[0]];
var result = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
var output = document.getElementById("result");
output.innerHTML = JSON.stringify(result, null, 2);
window.alert(result);
window.alert(result.type);
var array;
array = output.innerHTML;
output.parentNode.removeChild(output);
return array;
}
FR.onload = function(e) {
array = byDocument(e);
window.alert(array);
array.type = Array;
window.alert(array.type);
window.alert(array.length);
};
FR.readAsArrayBuffer(file);
});
</script>
This outputs text on the document that looks like an array, but when I try to store the data in a variable and index the array, it views the element array as some sort of string, or undefined. I'm wondering how to parse the excel file, or convert the JSON string, so that it behaves like a JavaScript array, which I could then index.
I believe it should be array = result instead of array = output.innerHTML. Or, at least, array = JSON.parse(ourput.innerHTML), because innerHTML is not an array, it's a string (you got it by JSON.strigify before).
It seems like you are already turning your result into JSON here:
var result = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
According to the documents of xlsx this will convert your excel file into workable JSON. So result might be the value you need to return instead of array in your byDocument function.
The line output.innerHTML = JSON.stringify(result, null, 2); will turn the object into JSON and put it in the DOM.
const myJSObject = JSON.parse(myJSON) will return a JavaScript object and assign it to a variable.
I took a few of the DOM lines out of your function to make it less confusing, so you could try replacing your function with:
function byDocument(e) {
var data = new Uint8Array(e.target.result);
var workbook = XLSX.read(data, { type: "array" });
var firstSheet = workbook.Sheets[workbook.SheetNames[0]];
var result = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
var array;
array = result
return array;
}
I am trying to search, find and fetch some data from a CSV file using HTML/PHP/Javascript.
I want to make a form with 2 dropdowns, one for the FROM Zone name and one for the TO Zone name, and use the Zone codes (102, 104, 105 etc) as values for the dropdown items.
After the user have selected the FROM and TO i want to display the single digit to the far right (col 5).
Example: User choose "Zone1" to "Zone4", then the number "4" should be returned.
FromZoneCode;FromZoneName;ToZoneCode;ToZoneName;Distance;;;;
101;zone1;101;zone1;1;;;;
101;zone1;104;zone4;4;;;;
101;zone1;105;zone5;5;;;;
104;zone4;101;zone1;4;;;;
104;zone4;105;zone5;2;;;;
104;zone4;104;zone4;1;;;;
I have tried to search for a solution for this but i cant seem to find the right info.
Worked out after a long time:
Don't know how you got the CSV data. In the following example, I got it by an ajax request.
No jQuery needed.
Created the dropdowns dynamically.
Set the variable delimeter to ; (or) , as required, because most CSV files contains CSV delimeter.
Give the names of the columns for which dropdowns to be created in the variables dropdownname1 and dropdownname2.
Give the name of the column to be displayed as result on chaning dropdowns in the variable resultname.
Create a <span> element with id="result" in the HTML to display the result.
Variable keys contains column names.
Variable values contains array of arrays as values.
var data = [];
$.ajax({
url:"/Users/Default/Downloads/test.csv",
type:"GET",
datatype:"csv",
success:function(response){
data = response.split(/\r\n/);
start();
}
});
//Logic starts here
//Initializations
var keys = [], values = [], delimiter = ";";
var dropdownname1 = "FromZoneName", dropdownname2 = "ToZoneName", resultname = "Distance";
var resultelem = document.getElementById("result");
//Functionalities
function createDropdown(field)
{
function createOption(option, isselected)
{
var optionelem = document.createElement("option");
optionelem.value=option;
optionelem.text=option;
optionelem.selected = isselected;
return optionelem;
}
var selectelem = document.createElement("select");
selectelem.setAttribute("id",field);
var insertedoptions = [];
for(var i=0;i<values.length;i++)
{
var option = values[i][keys.indexOf(field)];
if(insertedoptions.indexOf(option) == -1)
{
insertedoptions.push(option);
selectelem.appendChild(createOption(option));
}
}
selectelem.appendChild(createOption("",true));
return selectelem;
}
function start()
{
keys = data.splice(0,1)[0].split(delimiter);
values = [];
for(var i=0,n=data.length;i<n;i++)
{
values.push(data[i].split(delimiter));
}
var bodyelem = document.getElementsByTagName("body")[0];
bodyelem.appendChild(createDropdown(dropdownname1));
bodyelem.appendChild(createDropdown(dropdownname2));
document.getElementById(dropdownname1).addEventListener("change",displayData);
document.getElementById(dropdownname2).addEventListener("change",displayData);
}
function displayData()
{
var selectelem1 = document.getElementById(dropdownname1), selectelem2 = document.getElementById(dropdownname2);
var selectedvalue1 = selectelem1.value, selectedvalue2 = selectelem2.value;
for(var i=0,n=values.length;i<n;i++)
{
if(values[i][keys.indexOf(dropdownname1)] == selectedvalue1 && values[i][keys.indexOf(dropdownname2)] == selectedvalue2)
{
resultelem.innerHTML=values[i][keys.indexOf(resultname)];
break;
}
else
{
resultelem.innerHTML="";
}
}
}
I'm working with some CSV data. Right now the CSV has a column called 'characteristic' which is one of three types, and a column called 'value', which contains the numerical value for the characteristic.
I'd like to change the structure of the data so that the columns are the characteristics themselves, and the values fall directly under those columns.
Here are screenshots of the tables, for clarity:
Currently:
What I'd like:
I changed things manually to give an example. The actual table I'll need to change is thousands of lines, so I'm hoping I can do this programmatically in some way.
The reason I need to restructure is that I need to transform the CSV to JSON, and the JSON needs to look like this:
[
{
"country":"afghanistan",
"iso3":"afg",
"first_indicator":3,
"second_indicator":5,
"third_indicator":3
},
{
"country":"united states",
"iso3":"usa",
"first_indicator":8,
"second_indicator":6,
"third_indicator":7
},
{
"country":"china",
"iso3":"chn",
"first_indicator":6,
"second_indicator":0.7,
"third_indicator":2
}
]
So - is there any way to take my CSV as it is now (first screenshot), and transform it to the JSON I want, without doing it all manually?
I've done a lot of searching, and I think maybe I just don't know what to search for. Ideally I would use javascript for this, but any suggestions welcome.
Thank you.
I made a JSFiddle for you, something like this should be what you want.
JavaScript
function Country(name, short){
this["country"] = name;
this["iso3"] = short;
}
function getCountryByName(name) {
for(var i = 0; i < countries.length; i++){
var country = countries[i];
if(country["country"] == name){
return country;
}
}
return null;
}
var csv = "country,shortname,characteristics,value\nafghanistan,afg,first_characteristic,3\nunited states,usa,first_characteristic,8\nchina,chn,first_characteristic,6\nafghanistan,afg,second_characteristic,5\nunited states,usa,second_characteristic,6\nchina,chn,second_characteristic,0.7\nafghanistan,afg,third_characteristic,3\nunited states,usa,third_characteristic,7\nchina,chn,third_characteristic,2"
var rows = csv.split("\n");
var countries = [];
if(rows.length > 0){
var header = rows[0];
var columns = header.split(",");
var countryIndex = columns.indexOf("country");
var shortnameIndex = columns.indexOf("shortname");
var characteristicsIndex = columns.indexOf("characteristics");
var valueIndex = columns.indexOf("value");
for(var i = 1; i < rows.length; i++) {
var row = rows[i];
var columns = row.split(",");
var name = columns[countryIndex];
var short = columns[shortnameIndex];
var characteristic = columns[characteristicsIndex];
var value = columns[valueIndex];
var country = getCountryByName(name);
if(!country){
country = new Country(name, short);
countries.push(country);
}
country[characteristic.replace("characteristic", "indicator")] = +value;
}
}
console.log(countries);
console.log(JSON.stringify(countries));
Output from the last line is this:
[{"country":"afghanistan","iso3":"afg","first_indicator":"3","second_indicator":"5","third_indicator":"3"},
{"country":"united states","iso3":"usa","first_indicator":"8","second_indicator":"6","third_indicator":"7"},
{"country":"china","iso3":"chn","first_indicator":"6","second_indicator":"0.7","third_indicator":"2"}]
My suggestion is to convert the CSV to JSON first. You can use an online tool.
When you have the JSON you can write a Javascript code to modify the JSON in the format you want.
I have tried to find data-type of each column using Java Script, It prints string data-type for number,string and date.
I need each column data-type whether it is date or string or number or float.
Without CSV it prints correct data-type.
Working Example without CSV file
var num=15;
var str="xyz";
console.log(typeof num);
console.log(typeof str);
Output
number
string
But using csv file it prints string for all columns.
My CSV file is:
01/01/1991,12,xyz,14.4
01/01/1992,20,abc,20.5
01/02/1980,78,xy,60.8
I am using Papa Parse javascript plug-in for getting each column and then checking data-type.
How do I get each column's data-type from CSV file?
Is there any other way to parse CSV to array where we can traverse on particular row or column?
While you are loading your CSV in your javascript variable, that variable is a string.
You have to extract your csv into a JSON array and you have to cast each variable accordingly.
Code:
$.ajax({
type: "GET",
url: "sample.csv",
success: function (data) { loadData(data); }
});
/*var data = 'date,name,value\n\
01/01/1991,xyz,14.4\n\
01/01/1992,abc,20.5\n\
01/02/1980,xy,60.8';
loadData(data);*/
function loadData(data1){
console.log(data1);
var dataPoints = data1.split(/\r\n|\n/);
//console.log(lines);
var headers = dataPoints[0].split(','); // if you have header
var lines = [];
console.log(headers);
console.log(dataPoints.length);
for (var i = 1; i < dataPoints.length; i++) {
//console.log(i);
var point = dataPoints[i].split(',');
//console.log(point);
if (point.length == headers.length) {
var json= {};
for (var j = 0; j < headers.length; j++) {
if(headers[j]=='date'){
json[headers[j]] = new Date(point[j]);
}else if(headers[j]=='value'){
//console.log(point[j]);
json[headers[j]] = Number(point[j]);
}else{
json[headers[j]] = point[j];
}
}
lines.push(json);
console.log(json);
}
}
console.log(lines);
}
Sample CSV:
date,name,value
01/01/1991,xyz,14.4
01/01/1992,abc,20.5
01/02/1980,xy,60.8
Modified Code