From 3510146bc92a679801bb3ad38f719de896283e6d Mon Sep 17 00:00:00 2001 From: Jose Miguel Gallas Olmedo Date: Thu, 23 Feb 2017 12:57:55 +0100 Subject: [PATCH] allow renaming headers --- lib/parser/parser_stream.js | 19 +++++-- test/parsing.test.js | 104 ++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 5 deletions(-) diff --git a/lib/parser/parser_stream.js b/lib/parser/parser_stream.js index b93c1163..8b880c52 100644 --- a/lib/parser/parser_stream.js +++ b/lib/parser/parser_stream.js @@ -33,6 +33,7 @@ function ParserStream(options) { options.delimiter = delimiter; this.parser = createParser(options); this._headers = options.headers; + this._renameHeaders = options.renameHeaders; this._ignoreEmpty = options.ignoreEmpty; this._discardUnmappedColumns = options.discardUnmappedColumns; this._strictColumnHandling = options.strictColumnHandling; @@ -114,6 +115,7 @@ extended(ParserStream).extend({ __processHeaders: function (rows, cb) { var headers = this._headers, + renameHeaders = this._renameHeaders, discardUnmappedColumns = this._discardUnmappedColumns, strictColumnHandling = this._strictColumnHandling, self = this; @@ -142,7 +144,7 @@ extended(ParserStream).extend({ } while (++i < headersLength) { if (isUndefined(headers[i])) { - continue; + continue; } val = data[i]; ret[headers[i]] = isUndefined(val) ? '' : val; @@ -155,7 +157,14 @@ extended(ParserStream).extend({ cb(null); } - if (extended.isBoolean(headers) && headers) { + if (renameHeaders) { + if (Array.isArray(headers)) { + rows.shift(); + headerHandler(null, headers); + } else { + self.emit("error", new Error("Error renaming headers: new headers must be provided in an array")); + } + } else if (extended.isBoolean(headers) && headers) { this.__handleLine(rows.shift(), 0, true, headerHandler); } else { headerHandler(null, headers); @@ -198,9 +207,9 @@ extended(ParserStream).extend({ // Catches EFBBBF (UTF-8 BOM) because the buffer-to-string // conversion translates it to FEFF (UTF-16 BOM) if (data && typeof data == 'string' && data.charCodeAt(0) == '0xFEFF') { - return data.slice(1); - } - return data; + return data.slice(1); + } + return data; }, _transform: function (data, encoding, done) { diff --git a/test/parsing.test.js b/test/parsing.test.js index b69f9a24..cc61b702 100644 --- a/test/parsing.test.js +++ b/test/parsing.test.js @@ -440,6 +440,63 @@ var expected26 = [ var expected27 = expected26; +var expectedRenameHeaders = [ + { + "firstName": "First1", + "lastName": "Last1", + "emailAddress": "email1@email.com", + address: "1 Street St, State ST, 88888" + }, + { + "firstName": "First2", + "lastName": "Last2", + "emailAddress": "email2@email.com", + address: "2 Street St, State ST, 88888" + }, + { + "firstName": "First3", + "lastName": "Last3", + "emailAddress": "email3@email.com", + address: "3 Street St, State ST, 88888" + }, + { + "firstName": "First4", + "lastName": "Last4", + "emailAddress": "email4@email.com", + address: "4 Street St, State ST, 88888" + }, + { + "firstName": "First5", + "lastName": "Last5", + "emailAddress": "email5@email.com", + address: "5 Street St, State ST, 88888" + }, + { + "firstName": "First6", + "lastName": "Last6", + "emailAddress": "email6@email.com", + address: "6 Street St, State ST, 88888" + }, + { + "firstName": "First7", + "lastName": "Last7", + "emailAddress": "email7@email.com", + address: "7 Street St, State ST, 88888" + }, + { + "firstName": "First8", + "lastName": "Last8", + "emailAddress": "email8@email.com", + address: "8 Street St, State ST, 88888" + }, + { + "firstName": "First9", + "lastName": "Last9", + "emailAddress": "email9@email.com", + address: "9 Street St, State ST, 88888" + } +]; + it.describe("fast-csv parsing", function (it) { it.timeout(60000); @@ -605,6 +662,53 @@ it.describe("fast-csv parsing", function (it) { }); }); + it.should("allow renaming columns", function (next) { + var actual = []; + csv + .fromPath(path.resolve(__dirname, "./assets/test1.csv"), { headers: ["firstName", "lastName", "emailAddress", "address"], renameHeaders: true }) + .on("data", function (data, index) { + actual.push(data); + }) + .on("error", next) + .on("end", function (count) { + assert.deepEqual(actual, expectedRenameHeaders); + assert.equal(count, actual.length); + next(); + }); + }); + + it.should("propagate an error when trying to rename headers without providing new ones", function (next) { + var actual = []; + csv + .fromPath(path.resolve(__dirname, "./assets/test1.csv"), { renameHeaders: true }) + .on("data", function (data, index) { + actual.push(data); + }) + .on("error", function (err) { + assert.equal(err.message, "Error renaming headers: new headers must be provided in an array"); + next(); + }) + .on("end", function (count) { + next(new Error("Rename headers without headers error not propagated")); + }); + }); + + it.should("propagate an error when trying to rename headers without providing proper ones", function (next) { + var actual = []; + csv + .fromPath(path.resolve(__dirname, "./assets/test1.csv"), { renameHeaders: true, headers: true }) + .on("data", function (data, index) { + actual.push(data); + }) + .on("error", function (err) { + assert.equal(err.message, "Error renaming headers: new headers must be provided in an array"); + next(); + }) + .on("end", function (count) { + next(new Error("Rename headers without headers error not propagated")); + }); + }); + it.should("allow specifying of columns as a sparse array", function (next) { var actual = []; csv