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