How to rearrange CSV / JSON keys columns? (Javascript) - javascript

I am converting a JSON object array to CSV using Papa Parse JavaScript Library. Is there a way to have the CSV columns arranged in a certain way.
For e.g; I get the column as:
OrderStatus, canOp, OpDesc, ID, OrderNumber, FinishTime, UOM, StartTime
but would like to be arranged as:
ID, OrderNumber, OrderStatus, StartTime, FinishTime, canOp, OpDesc, UOM
The reason why I get the CSV as unarranged is because the JSON data looks like this:
json = [
{
OrderStatus: "Good",
canOp:"True",
OpDesc:"Good to go",
ID:"100",
OrderNumber:"1000101",
FinishTime:"20:50",
UOM:"K",
StartTime:"18:10"
},
...
]
Thanks

Papa Parse allows to specify order of fields in the unparse() function:
var csv = Papa.unparse({
fields: ["ID", "OrderNumber", "OrderStatus", "StartTime", "FinishTime", "canOp", "OpDesc", "UOM"],
data: [{
OrderStatus: "Good",
canOp: "True",
OpDesc: "Good to go",
ID: "100",
OrderNumber: "1000101",
FinishTime: "20:50",
UOM: "K",
StartTime: "18:10"
},
// ...
]
});
console.log(csv);
<script src="https://unpkg.com/papaparse#4.6.3/papaparse.min.js"></script>
<h3>See your dev console for the results</h3>

You don't need any framework to convert from json to csv.
// fields in the order you want them
const fields = ['ID', 'OrderNumber', 'OrderStatus', 'StartTime', 'FinishTime', 'canOp', 'OpDesc', 'UOM'];
const mapper = (key, value) => value === null ? '' : value // how to handle null values
const csv = [
fields.join(','), // header row
...json.map((row) => fields.map((fieldName) => JSON.stringify(row[fieldName], mapper))).join(',')
]
console.log(csv.join('\r\n'))
Outputs:
ID,OrderNumber,OrderStatus,StartTime,FinishTime,canOp,OpDesc,UOM
"100","1000101","Good","18:10","20:50","True","Good to go","K"
"100","1000101","Good","18:10","20:50","True","Good to go","K"

Related

JavaScript: List of dictionaries(JSON) to csv

I am doing some operation on list of dictionaries and at the end want to save the data in the form of csv in browser's local storage.
My list of dictionaries data looks like this:
[{
arrivalAddress: "Address"
arrivalLat: "72.989506"
arrivalLon: "19.149307"
arrivalTimeEnd: "8/8/2020 13:37"
arrivalTimeStart: "8/8/2020 13:37"
carrier: "ABC"
departureAddress: "abc,sdkfnv"
departureLat: "73.008304"
departureLon: "19.114599"
departureTime: "8/8/2020 13:37"
hazardousGoods: "TRUE"
id: "1"
"receiver ": "Tom"
sender: "Jack"
tourID: "abc"
vehicleClass: "eu_heavy"
},
arrivalAddress: "Address"
arrivalLat: "72.989506"
arrivalLon: "19.149307"
arrivalTimeEnd: "8/8/2020 13:37"
arrivalTimeStart: "8/8/2020 13:37"
carrier: "ABC"
departureAddress: "abc,sdkfnv"
departureLat: "73.008304"
departureLon: "19.114599"
departureTime: "8/8/2020 13:37"
hazardousGoods: "TRUE"
id: "1"
"receiver ": "Tom"
sender: "Jack"
tourID: "abc"
vehicleClass: "eu_heavy"
},
......
]
And I want it to save in browser's local storage like this:
Can anyone help me to convert list of dicts to csv?
I think this should do it.
const listOfDicts = [...];
const dictionaryKeys = Object.keys(listOfDicts[0]);
const dictValuesAsCsv = listOfDicts.map(dict => (
dictionaryKeys.map(key => dict[key]).join(',')
));
const result = [dictionaryKeys.join(','), ...dictValuesAsCsv].join('\n');
Mind you, the order of the keys might not be correct, for that you should first sort dictionaryKeys to be in the correct order (if the keys are constant, you can replace const dictionaryKeys = Object.keys(listOfDicts[0]); with const dictionaryKeys = ['key1', 'key2', ...];)
Edit:
To answer your question about commas in the values, here's the change you should make
const dictValuesAsCsv = listOfDicts.map(dict => (
dictionaryKeys.map(key => {
if (dict[key].includes(',')) {
return `"${dict[key]}"`;
}
return dict[key];
}).join(',')
));
Explanation: the only difference is that you don't simply return dict[key], but rather you first check if it contains a comma; if it does, you wrap it in quotes, else it stays as before.

Looping through an array of objects and mapping each object them to a single template object

I have a two sets of data, one formatted like so:
title: "Test Json",
showProgressBar: "top",
showQuestionNumbers: "off",
pages: [
{
questions: [
{
type: "",
name: "",
title: "",
hasOther: true,
isRequired: true,
colCount: 4,
choices: []
}
]
}
]
};
The other formatted like so:
{Answers: "“18-24”, “25-50”, “50+”",
​
Question: "How old are you?",
​
QuestionNumber: "1",
​
isRequired: "TRUE",
​
type: "radiogroup"}
This second set of data is multiple of these objects, which I am looping through using a forEach loop like so:
data.forEach((data, i)=>{
console.log(data)
// returns above object x3
})
What I want to do is use the first object and map values to the questions array using the values of the second object, so for example questions[0].type would be mapped to data.type.
I have managed to figure out mapping one object to the template doing this:
data.forEach((data, i)=>{
console.log(data)
questions[0].type = data.type
questions[0].name = data.Question
questions[0].title = data.Question
questions[0].choices = [data.Answers]
})
But this only maps the first object in the data array of objects, and I want to basically create a new template object based on the number of objects in the data array and create as many 'filled questions templates' as there is objects in data array
Any pointers and help would be lovely <3
Try this
data.forEach((data, i)=>{
console.log(data)
questions.push([{
type: data.type
name: data.Question
title: data.Question
choices: [data.Answers]
}])
})
Updated this answer with your additional question

Read XLSX to from the update query

I am using XLSX NPM to read the XLSX file and i converted to json as like below
My Xlsx sheet is of format:..
skill id name xx
abc 4578 express-basic 30
4698 express-advanced 60
qwerty 7856 express-basic 90
MY Json:
[ { skill: 'abc',
id: 4578,
name: 'express-basic',
xx: 30 },
{ id: 4689, name: 'express-advanced', xx: 60 },
{ skill: 'qwerty',
id: 7856,
name: 'express-advanced',
xx: 90 } ]
I have to update collection X where id=4578,4689 ass skill = abc so how can i convert the below json into as follows:
[
{'abc':[4578,4689]},
{'qwerty':[7856]}
]
so that i can loop through this and i can update the collectionX. My problem is how can i know the next skill is starting from the json and construct the Above array. Thanks...
You Can work with array.reduce.
YOUR_JSON_ARRAY.reduce(function (obj, item) {
obj[item.skill] = obj[item.skill] || [];
obj[item.skill].push(item.id);
return obj;
}, {});
Above code will groupBy your Array by using item.skill key.
P.S. you need to handle this if item.skill doesn't exists,
otherwise it will create undefined key:value pair.
Hope it will help.

Generic way of Json to CSV converting for generic deep nested arrays

I am programing a function, that should convert generic deep nested JSON object levels to CSV file in JS or TypeScript.
I tried several libraries but somehow they don't work the way i want it to unwind the nested JSON right. The code should unwind this input:
{
[
{
app: "app1",
device: [
"c1",
"c2",
"c3",
"c4"
]
},
{
app: "app2",
device: [
"b1",
"b2"
]
}
]
}
Into this expected result:
app;device
app1;c1
app1;c2
app1;c3
app1;c4
app2;b1
app2;b2
Right now I'm using this code but the result is not like expected:
private ConvertToCSV(json: string, fields: string[]): string {
const Json2csvParser = require("json2csv").Parser;
let options: {};
options = { fields };
const parser = new Json2csvParser(options);
const csv = parser.parse(JSON.parse(json));
console.log(JSON.parse(json));
console.log(csv);
return csv;
}
My result right now looks like this:
"app","device"
"app1","[""c1"",""c2"",""c3"",""c4""]"
"app2","[""b1"",""b2""]"
Yes, you can do this -- it's right in the docs with the unwind function though you may need to add a transformer to format it exactly how you want. Take a look:
const data: any = [
{
app: "app1",
device: [
"c1",
"c2",
"c3",
"c4"
]
},
{
app: "app2",
device: [
"b1",
"b2"
]
}
];
function ConvertToCSV(json: string, fields: any): string {
const Json2csvParser = require("json2csv").parse;
let options: {};
options = fields;
const csv = Json2csvParser(JSON.parse(json), options);
console.log(JSON.parse(json));
console.log(csv);
return csv;
}
ConvertToCSV(JSON.stringify(data), {fields: ['app', 'device'], unwind: 'device'});
Let me know if this solves your issue, or if it doesn't. I have some experience with this lib and may be able to help
I'd recommend flattening your data and then just using the csv parser you have.
function flattenData(data,groupingField,flattenedField) {
let flattenedData =[];
data.forEach(d => {
d[flattenedField].forEach(sd => {
flattenedData.push({[groupingField]: d[groupingField], [flattenedField]: sd});
});
});
return flattenedData;
}
Then you'll have a data structure your csv parser knows how to deal with.

How to map model to table when the structure is array based?

I have my data as following:
{
meta: {
format: "csv",
info: "desc",
columns: [
{
id: "Name",
type: "Text",
length: 32
},
{
id: "Text",
type: "Text",
length: 128
}]
},
rows: [
["John","xxxx"],
["Alpha","yyyy"],
["Beta","wwww"],
["Gamma","zzzz"]]
}
Now, I am struggling to map the records to a Table control as Columns and Rows. Column seems straight forward, straight map, but the rows since lacks a mapping to column I wonder what could be the simplest way.
Approach Steps:
Make a keys[] from column.id of each columns record.
Traverse the rows[]
Each loop, while keys.length create an object as {keys[j]:row[k]}
Push to an array
Recreate the original JSON but replace Rows arrays with Objects
I am really struggling to translate this into code specially at the rows[] parsing and creating Objects. Is there, I am sure there must be, an efficient way to achieve this.
Here is what you could do. using Array.map and forEach.
var input = {
meta: {
format: "csv",
info: "desc",
columns: [{
id: "Name",
type: "Text",
length: 32
}, {
id: "Text",
type: "Text",
length: 128
}]
},
rows: [
["John", "xxxx"],
["Alpha", "yyyy"],
["Beta", "wwww"],
["Gamma", "zzzz"]
]
};
var columns = input.meta.columns.map((column) => {
return column.id
});
var rows = input.rows.map((row) => {
var obj = {};
row.forEach((column, idx) => {
obj[columns[idx]] = column;
});
return obj;
});
input.rows = rows;
console.log(input);

Categories

Resources