diff --git a/src/lil-csv.js b/src/lil-csv.js index 50b9bd8..ebdafcc 100644 --- a/src/lil-csv.js +++ b/src/lil-csv.js @@ -1,9 +1,18 @@ -export const isString = (v) => typeof v === "string"; -export const isNumber = (v) => typeof v === "number"; -export const isBoolean = (v) => typeof v === "boolean"; -export const isDate = (v) => v instanceof Date && !isNaN(v.valueOf()); -export const isObject = (v) => v && typeof v === "object"; -export const isFunction = (v) => typeof v === "function"; +const isString = (v) => typeof v === "string"; +const isNumber = (v) => typeof v === "number"; +const isBoolean = (v) => typeof v === "boolean"; +const isDate = (v) => v instanceof Date && !isNaN(v.valueOf()); +const isObject = (v) => v && typeof v === "object"; +const isFunction = (v) => typeof v === "function"; +// function getDeep(obj, path) { +// return path.split(".").reduce((result, curr) => (result == null ? result : result[curr]), obj); +// } +function setDeep(obj, path, value) { + path.split(".").reduce((result, curr, index, paths) => { + const newVal = index + 1 === paths.length ? value : {}; + return isObject(result[curr]) ? result[curr] : (result[curr] = newVal); + }, obj); +} export function parse(str, { header = true, escapeChar = "\\" } = {}) { const entries = []; @@ -73,13 +82,15 @@ export function parse(str, { header = true, escapeChar = "\\" } = {}) { const processedEntry = {}; for (let col = 0; col < entry.length; col++) { const dataHeaderName = headerEntry[col]; - if (!header[dataHeaderName]) continue; // We don't want this column + const dataHeader = header[dataHeaderName]; + if (!dataHeader) continue; // We don't want this column let value = entry[col]; - const parse = header[dataHeaderName].parse || header[dataHeaderName]; + const parse = dataHeader.parse || dataHeader; if (isFunction(parse)) value = parse(value); - processedEntry[header[dataHeaderName].jsonName || dataHeaderName] = value; + let propName = dataHeader.jsonName || (isString(dataHeader) ? dataHeader : dataHeaderName); + setDeep(processedEntry, propName, value); } return processedEntry; }); diff --git a/test/lil-csv.test.js b/test/lil-csv.test.js index 5aec947..a7a3ae9 100644 --- a/test/lil-csv.test.js +++ b/test/lil-csv.test.js @@ -3,7 +3,72 @@ import { parse, generate } from "../src/lil-csv"; const assert = require("assert"); describe("parse", () => { - it("should parse", () => { + it("should parse objects", () => { + const text = `Column,Second Column,else\rhere, we go ,false\r\n"with,comma","with \\" escaped quotes",123\n"",empty, +`; + const rows = parse(text); + assert.deepStrictEqual(rows, [ + { Column: "here", "Second Column": " we go ", else: "false" }, + { Column: "with,comma", "Second Column": 'with " escaped quotes', else: "123" }, + { Column: "", "Second Column": "empty", else: "" }, + ]); + }); + + it("should parse objects and rename headers", () => { + const text = `Column,Second Column,else\rhere, we go ,false\r\n"with,comma","with \\" escaped quotes",123\n"",empty, +`; + const rows = parse(text, { + header: { Column: true, "Second Column": { jsonName: "Column2" }, else: "Column3" }, + }); + assert.deepStrictEqual(rows, [ + { Column: "here", Column2: " we go ", Column3: "false" }, + { Column: "with,comma", Column2: 'with " escaped quotes', Column3: "123" }, + { Column: "", Column2: "empty", Column3: "" }, + ]); + }); + + it("should parse objects and rename headers deeply", () => { + const text = `Column,Second Column,else\rhere, we go ,false\r\n"with,comma","with \\" escaped quotes",123\n"",empty, +`; + const rows = parse(text, { + header: { + Column: true, + "Second Column": { jsonName: "deep.Column2" }, + else: "deep.veryDeep.Column3", + }, + }); + assert.deepStrictEqual(rows, [ + { + Column: "here", + deep: { + Column2: " we go ", + veryDeep: { + Column3: "false", + }, + }, + }, + { + Column: "with,comma", + deep: { + Column2: 'with " escaped quotes', + veryDeep: { + Column3: "123", + }, + }, + }, + { + Column: "", + deep: { + Column2: "empty", + veryDeep: { + Column3: "", + }, + }, + }, + ]); + }); + + it("should parse without header", () => { const text = `Column,Second Column,else\rhere, we go ,false\r\n"with,comma","with \\" escaped quotes",123\n"",empty, `; const rows = parse(text, { header: false });