2023-05-02 11:34:45 +02:00
|
|
|
import csv from "csvtojson"
|
|
|
|
|
|
|
|
export async function jsonFromCsvString(csvString: string) {
|
2025-01-31 11:40:03 +01:00
|
|
|
const possibleDelimiters = [",", ";", ":", "|", "~", "\t", " "]
|
2023-05-02 12:57:18 +02:00
|
|
|
|
2025-01-31 11:40:03 +01:00
|
|
|
for (let i = 0; i < possibleDelimiters.length; i++) {
|
2025-01-29 18:52:14 +01:00
|
|
|
let headers: string[] | undefined = undefined
|
2025-01-29 16:42:33 +01:00
|
|
|
let headerMismatch = false
|
|
|
|
|
2025-01-29 17:39:21 +01:00
|
|
|
try {
|
|
|
|
// By default the csvtojson library casts empty values as empty strings. This
|
|
|
|
// is causing issues on conversion. ignoreEmpty will remove the key completly
|
|
|
|
// if empty, so creating this empty object will ensure we return the values
|
|
|
|
// with the keys but empty values
|
|
|
|
const result = await csv({
|
|
|
|
ignoreEmpty: false,
|
2025-01-31 11:40:03 +01:00
|
|
|
delimiter: possibleDelimiters[i],
|
2025-01-29 17:39:21 +01:00
|
|
|
}).fromString(csvString)
|
2025-01-31 11:51:22 +01:00
|
|
|
for (const [, row] of result.entries()) {
|
2025-01-29 17:39:21 +01:00
|
|
|
// The purpose of this is to find rows that have been split
|
|
|
|
// into the wrong number of columns - Any valid .CSV file will have
|
|
|
|
// the same number of colums in each row
|
|
|
|
// If the number of columms in each row is different to
|
|
|
|
// the number of headers, this isn't the right delimiter
|
2025-01-31 11:51:22 +01:00
|
|
|
const columns = Object.keys(row)
|
2025-01-29 18:52:14 +01:00
|
|
|
if (headers == null) {
|
|
|
|
headers = columns
|
2025-01-29 17:39:21 +01:00
|
|
|
}
|
2025-01-29 18:52:14 +01:00
|
|
|
if (headers.length === 1 || headers.length !== columns.length) {
|
2025-01-29 17:39:21 +01:00
|
|
|
headerMismatch = true
|
|
|
|
break
|
|
|
|
}
|
2025-01-29 18:52:14 +01:00
|
|
|
|
|
|
|
for (const header of headers) {
|
2025-01-31 11:51:22 +01:00
|
|
|
if (row[header] === undefined || row[header] === "") {
|
|
|
|
row[header] = null
|
2025-01-29 17:39:21 +01:00
|
|
|
}
|
|
|
|
}
|
2025-01-29 16:42:33 +01:00
|
|
|
}
|
2025-01-29 17:39:21 +01:00
|
|
|
if (headerMismatch) {
|
|
|
|
continue
|
|
|
|
} else {
|
|
|
|
return result
|
2025-01-29 16:42:33 +01:00
|
|
|
}
|
2025-01-29 17:39:21 +01:00
|
|
|
} catch (err) {
|
|
|
|
// Splitting on the wrong delimiter sometimes throws CSV parsing error
|
|
|
|
// (eg unterminated strings), which tells us we've picked the wrong delimiter
|
2025-01-29 16:42:33 +01:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw new Error("Unable to determine delimiter")
|
2023-05-02 11:34:45 +02:00
|
|
|
}
|