I have an array of JSON objects that I'm trying to convert to CSV where the end format would look something like this in excel:
url | id | type |
---|---|---|
http://www.example.com | F22 | a11y-true |
C30 | a11y-unknown | |
RC30 | a11y-true | |
http://www.example.com/something-else | F22 | a11y-true |
F23 | a11y-true | |
U10 | a11y-unknown | |
CR14 | a11y-unknown | |
RH03 | a11y-true |
given data such as...
[
{
"url": "https://www.example.com/something",
"ids": [
{ "id": "F22", "type": "a11y-true" },
{ "id": "C30", "type": "a11y-unknown" }
]
},
{
"url": "https://www.example.com/something-else",
"ids": [
{ "id": "F23", "type": "a11y-true" },
{ "id": "U10", "type": "a11y-unknown" },
{ "id": "CR14", "type": "a11y-unknown" },
{ "id": "RH03", "type": "a11y-true" }
]
}
]
I tried converting the JSON using:
const items = data
const header = Object.keys(items[0])
const csv = [header.join(','),...items.map(row => header.map(fieldName => JSON.stringify(row[fieldName])).join(','))].join('\r\n')
console.log(csv)
but I end up with only the first level converted over:
"https://www.example.com/something",[{"id":"F22","type":"a11y-true"},{"id":"C30","type":"a11y-unknown"}]
"https://www.example.com/something-else",[{"id":"F23","type":"a11y-true"},{"id":"U10","type":"a11y-unknown"},{"id":"CR14","type":"a11y-unknown"},{"id":"RH03","type":"a11y-true"}]
How can I also get the nested arrays converted to CSV so that each {}
is a single entry?
CodePudding user response:
There are libraries for working with csv in js but you could just define header fields and then pick those field values when you loop over ids
const data = [{"url":"https://www.example.com/something","ids":[{"id":"F22","type":"a11y-true"},{"id":"C30","type":"a11y-unknown"}]},{"url":"https://www.example.com/something-else","ids":[{"id":"F23","type":"a11y-true"},{"id":"U10","type":"a11y-unknown"},{"id":"CR14","type":"a11y-unknown"},{"id":"RH03","type":"a11y-true"}]}]
const separator = ', '
const header = ["url", "id", 'type']
const body = data.reduce((r, { url, ids }) => {
ids.forEach((e, i) => {
const first = i === 0 ? url : ''
const other = header.slice(1).map(k => e[k]).join(separator)
r.push([first, other].join(separator))
})
return r
}, [])
const result = `${header.join(separator)}\n${body.join('\n')}`
console.log(result)
CodePudding user response:
You can do something like this:
const data = [
{
"url": "https://www.example.com/something",
"ids": [
{ "id": "F22", "type": "a11y-true" },
{ "id": "C30", "type": "a11y-unknown" }
]
},
{
"url": "https://www.example.com/something-else",
"ids": [
{ "id": "F23", "type": "a11y-true" },
{ "id": "U10", "type": "a11y-unknown" },
{ "id": "CR14", "type": "a11y-unknown" },
{ "id": "RH03", "type": "a11y-true" }
]
}
];
const headers = ["url", "id", 'type'];
const res = data.reduce((a,b)=>{
const [firstRow, ...rest] = b.ids;
const firstPart = `${b.url},${Object.values(firstRow).join()}\n`
const restOfThePart = rest.map(it=>`,${Object.values(it).join()}`).join('\n');
return `${a}${firstPart}${restOfThePart}\n`;
},'');
console.log(`${headers}\n${res}`);