Home > database >  Convert JSON array and nested data to CSV
Convert JSON array and nested data to CSV

Time:11-30

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}`);

  • Related