import csv from "csvtojson" export async function jsonFromCsvString(csvString: string) { const possibleDelimiters = [",", ";", ":", "|", "~", "\t", " "] for (let i = 0; i < possibleDelimiters.length; i++) { let headers: string[] | undefined = undefined let headerMismatch = false 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, delimiter: possibleDelimiters[i], }).fromString(csvString) for (const [, row] of result.entries()) { // 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 const columns = Object.keys(row) if (headers == null) { headers = columns } if (headers.length === 1 || headers.length !== columns.length) { headerMismatch = true break } for (const header of headers) { if (row[header] === undefined || row[header] === "") { row[header] = null } } } if (headerMismatch) { continue } else { return result } } catch (err) { // Splitting on the wrong delimiter sometimes throws CSV parsing error // (eg unterminated strings), which tells us we've picked the wrong delimiter continue } } throw new Error("Unable to determine delimiter") }