Skip to content

Instantly share code, notes, and snippets.

@T99
Last active September 14, 2021 17:27
Show Gist options
  • Save T99/effc9a7f66fd8ceb23352f9a0779d319 to your computer and use it in GitHub Desktop.
Save T99/effc9a7f66fd8ceb23352f9a0779d319 to your computer and use it in GitHub Desktop.
Convert JSON data to CSV data.
/*
* Created by Trevor Sears <[email protected]> (https://trevorsears.com/).
* 12:43 PM -- September 14th, 2021
*/
/**
* Returns all of the unique properties found in any of the objects within the given array.
*
* @param {T[]} jsonArray The array of objects over which to build a list of unique properties.
* @returns {Array<keyof T>} An array containing all of the unique properties found in any of the objects within the
* given array.
*/
function getAllUniqueProps<T>(jsonArray: T[]): Array<keyof T> {
let props: Set<keyof T> = new Set();
for (let json of jsonArray) {
for (let prop of Object.getOwnPropertyNames(json)) {
props.add(prop as keyof T);
}
}
return [...props];
}
/**
* Returns a 'cleaned' string representation of the input value.
*
* This is the default 'cleaner' function used to sanitize/clean CSV data for the `jsonToCSV` function.
*
* @param {any} value The value to 'clean'.
* @param {string} separator The separator string being used in the relevant CSV data.
* @returns {string} A 'cleaned' version of the input value.
*/
function cleanCSVData(value: any, separator: string): string {
if (value === true) return "1";
else if (value === false) return "0";
if (typeof value === "string" && value.includes(separator)) return `"${value}"`;
return value;
}
/**
* Converts a JSON array to a CSV-style string, returning the result.
*
* @param {T[]} jsonArray The array of objects from which to source the data for the CSV string result.
* @param {Array<keyof T>} fields An optional array of strings that will be used as the fields of the resulting CSV.
* @param {string} separator The string to use to separate cells in the resulting data.
* @param {(value: string) => string} cleaner An optional callback that will be applied to every value (cell) before
* being used in the output string.
* @returns {string} A string representation of the generated CSV data.
*/
export function jsonToCSV<T>(jsonArray: T[],
fields: Array<keyof T> = getAllUniqueProps(jsonArray),
separator: string = ",",
cleaner: (value: any, separator: string) => string = cleanCSVData): string {
let result: string = "";
result += fields.join(separator);
for (let json of jsonArray) {
let values: string[] = fields.map((property: keyof T): string => cleaner(json[property], separator));
result += `\n${values.join(separator)}`;
}
return result;
}
// Example usage:
console.log(jsonToCSV([
{
id: 1,
name: "John"
},
{
id: 2,
name: "Jess"
},
{
id: 3,
name: "Junior"
}
]));
/* id,name
* 1,John
* 2,Jess
* 3,Junior
*/
console.log(jsonToCSV([
{
id: 1,
name: "John",
email: "[email protected]"
},
{
id: 2,
name: "Jess",
phone: "(123) 456 - 7890"
},
{
id: 3,
name: "Junior",
fax: "no one uses fax anymore"
}
], undefined, "|"));
/* id|name|email|phone|fax
* 1|John|[email protected]||
* 2|Jess||(123) 456 - 7890|
* 3|Junior|||no one uses fax anymore
*/
console.log(jsonToCSV([
{
id: 1,
name: "John"
},
{
id: 2,
name: "Jess"
},
{
id: 3,
name: "Junior"
}
], ["fields", "that", "don't", "exist"]));
/* fields,that,don't,exist
* ,,,
* ,,,
* ,,,
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment