From eccca89dd54604cd185d56fd780b3e60db3c0fc1 Mon Sep 17 00:00:00 2001 From: Juanjo Diaz Date: Tue, 10 Apr 2018 05:28:29 +0300 Subject: [PATCH] fix: Support empty array with opts.fields (#281) --- lib/JSON2CSVParser.js | 2 +- lib/JSON2CSVTransform.js | 23 +++++++++++++++++------ test/JSON2CSVParser.js | 12 ++++++++++++ test/JSON2CSVTransform.js | 18 ++++++++++++++++++ test/fixtures/json/emptyArray.json | 1 + 5 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 test/fixtures/json/emptyArray.json diff --git a/lib/JSON2CSVParser.js b/lib/JSON2CSVParser.js index e4e25062..4d7c29fa 100644 --- a/lib/JSON2CSVParser.js +++ b/lib/JSON2CSVParser.js @@ -40,7 +40,7 @@ class JSON2CSVParser extends JSON2CSVBase { preprocessData(data) { const processedData = Array.isArray(data) ? data : [data]; - if (!this.opts.fields && processedData.length === 0 || typeof processedData[0] !== 'object') { + if (!this.opts.fields && (processedData.length === 0 || typeof processedData[0] !== 'object')) { throw new Error('Data should not be empty or the "fields" option should be included'); } diff --git a/lib/JSON2CSVTransform.js b/lib/JSON2CSVTransform.js index e53808c8..bbc527cc 100644 --- a/lib/JSON2CSVTransform.js +++ b/lib/JSON2CSVTransform.js @@ -27,6 +27,10 @@ class JSON2CSVTransform extends Transform { this.push('\ufeff'); } + if (this.opts.fields) { + this.pushHeader(); + } + } /** @@ -120,6 +124,18 @@ class JSON2CSVTransform extends Transform { done(); } + /** + * Generate the csv header and pushes it downstream. + */ + pushHeader() { + if (this.opts.header) { + const header = this.getHeader(this.opts); + this.emit('header', header); + this.push(header); + this._hasWritten = true; + } + } + /** * Transforms an incoming json data to csv and pushes it downstream. * @@ -130,12 +146,7 @@ class JSON2CSVTransform extends Transform { if (!this._hasWritten) { this.opts.fields = this.opts.fields || Object.keys(processedData[0]); - if (this.opts.header) { - const header = this.getHeader(this.opts); - this.emit('header', header); - this.push(header); - this._hasWritten = true; - } + this.pushHeader(); } processedData.forEach(row => { diff --git a/test/JSON2CSVParser.js b/test/JSON2CSVParser.js index 8cd7c87c..28f9fcb6 100644 --- a/test/JSON2CSVParser.js +++ b/test/JSON2CSVParser.js @@ -37,6 +37,18 @@ module.exports = (testRunner, jsonFixtures, csvFixtures) => { t.end(); }); + testRunner.add('should handle empty array', (t) => { + const opts = { + fields: ['carModel', 'price', 'color'] + }; + + const parser = new Json2csvParser(opts); + const csv = parser.parse(jsonFixtures.emptyArray); + + t.equal(csv, csvFixtures.emptyObject); + t.end(); + }); + testRunner.add('should hanlde array with nulls', (t) => { const input = [null]; const opts = { diff --git a/test/JSON2CSVTransform.js b/test/JSON2CSVTransform.js index d8822e42..238a9b93 100644 --- a/test/JSON2CSVTransform.js +++ b/test/JSON2CSVTransform.js @@ -97,6 +97,24 @@ module.exports = (testRunner, jsonFixtures, csvFixtures) => { .on('error', err => t.notOk(true, err.message)); }); + testRunner.add('should handle empty array', (t) => { + const opts = { + fields: ['carModel', 'price', 'color'] + }; + + const transform = new Json2csvTransform(opts); + const processor = jsonFixtures.emptyArray().pipe(transform); + + let csv = ''; + processor + .on('data', chunk => (csv += chunk.toString())) + .on('end', () => { + t.equal(csv, csvFixtures.emptyObject); + t.end(); + }) + .on('error', err => t.notOk(true, err.message)); + }); + testRunner.add('should hanlde array with nulls', (t) => { const input = new Readable(); input._read = () => {}; diff --git a/test/fixtures/json/emptyArray.json b/test/fixtures/json/emptyArray.json new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/test/fixtures/json/emptyArray.json @@ -0,0 +1 @@ +[] \ No newline at end of file