Comparing version 4.0.0-alpha.1 to 4.0.0-alpha.2
@@ -8,4 +8,4 @@ 'use strict'; | ||
class TablePrinter { | ||
constructor(params) { | ||
this.params = params; | ||
constructor(opts) { | ||
this.opts = opts; | ||
this._hasWritten = false; | ||
@@ -16,3 +16,3 @@ this.colWidths; | ||
push(csv) { | ||
const lines = csv.split(this.params.eol); | ||
const lines = csv.split(this.opts.eol); | ||
@@ -27,4 +27,4 @@ const chars = { | ||
this.colWidths = this.getColumnWidths(lines[0]); | ||
if (this.params.header) { | ||
const head = lines.shift().split(this.params.delimiter); | ||
if (this.opts.header) { | ||
const head = lines.shift().split(this.opts.delimiter); | ||
const table = new Table({ head, colWidths: this.colWidths, chars }); | ||
@@ -48,3 +48,3 @@ this.print(table, []); | ||
end(csv) { | ||
const lines = csv.split(this.params.eol); | ||
const lines = csv.split(this.opts.eol); | ||
const chars = { 'top-left': '├' , 'top-mid': '┼', 'top-right': '┤' }; | ||
@@ -56,7 +56,7 @@ const table = new Table({ colWidths: this.colWidths, chars }); | ||
printCSV(csv) { | ||
let lines = csv.split(this.params.eol); | ||
let lines = csv.split(this.opts.eol); | ||
this.colWidths = this.getColumnWidths(lines[0]); | ||
const head = this.params.header | ||
? lines.shift().split(this.params.delimiter) | ||
const head = this.opts.header | ||
? lines.shift().split(this.opts.delimiter) | ||
: undefined; | ||
@@ -73,3 +73,3 @@ | ||
return line | ||
.split(this.params.delimiter) | ||
.split(this.opts.delimiter) | ||
.map(elem => Math.max(elem.length * 2, MIN_CELL_WIDTH)); | ||
@@ -79,3 +79,3 @@ } | ||
print(table, lines) { | ||
lines.forEach(line => table.push(line.split(this.params.delimiter))); | ||
lines.forEach(line => table.push(line.split(this.opts.delimiter))); | ||
// eslint-disable-next-line no-console | ||
@@ -82,0 +82,0 @@ console.log(table.toString()); |
@@ -5,2 +5,12 @@ # Change Log | ||
<a name="4.0.0-alpha.2"></a> | ||
# [4.0.0-alpha.2](https://github.com/zemirco/json2csv/compare/v4.0.0-alpha.1...v4.0.0-alpha.2) (2018-02-25) | ||
### Bug Fixes | ||
* flatten issue with toJSON ([#259](https://github.com/zemirco/json2csv/issues/259)) ([7006d2b](https://github.com/zemirco/json2csv/commit/7006d2b)) | ||
<a name="4.0.0-alpha.1"></a> | ||
@@ -7,0 +17,0 @@ # [4.0.0-alpha.1](https://github.com/zemirco/json2csv/compare/v4.0.0-alpha.0...v4.0.0-alpha.1) (2018-02-21) |
@@ -7,34 +7,33 @@ 'use strict'; | ||
const lodashCloneDeep = require('lodash.clonedeep'); | ||
const flatten = require('flat'); | ||
class JSON2CSVBase { | ||
constructor(params) { | ||
this.params = this.preprocessParams(params); | ||
constructor(opts) { | ||
this.opts = this.preprocessOpts(opts); | ||
} | ||
/** | ||
* Check passing params and set defaults. | ||
* Check passing opts and set defaults. | ||
* | ||
* @param {Json2CsvParams} params Function parameters containing fields, | ||
* delimiter, default value, mark quote and header | ||
* @param {Json2CsvOptions} opts Options object containing fields, | ||
* delimiter, default value, quote mark, header, etc. | ||
*/ | ||
preprocessParams(params) { | ||
const processedParams = params || {}; | ||
processedParams.unwind = !Array.isArray(processedParams.unwind) | ||
? (processedParams.unwind ? [processedParams.unwind] : []) | ||
: processedParams.unwind | ||
processedParams.delimiter = processedParams.delimiter || ','; | ||
processedParams.eol = processedParams.eol || os.EOL; | ||
processedParams.quote = typeof processedParams.quote === 'string' | ||
? params.quote | ||
preprocessOpts(opts) { | ||
const processedOpts = opts || {}; | ||
processedOpts.unwind = !Array.isArray(processedOpts.unwind) | ||
? (processedOpts.unwind ? [processedOpts.unwind] : []) | ||
: processedOpts.unwind | ||
processedOpts.delimiter = processedOpts.delimiter || ','; | ||
processedOpts.eol = processedOpts.eol || os.EOL; | ||
processedOpts.quote = typeof processedOpts.quote === 'string' | ||
? opts.quote | ||
: '"'; | ||
processedParams.doubleQuote = typeof processedParams.doubleQuote === 'string' | ||
? processedParams.doubleQuote | ||
: Array(3).join(processedParams.quote); | ||
processedParams.defaultValue = processedParams.defaultValue; | ||
processedParams.header = processedParams.header !== false; | ||
processedParams.includeEmptyRows = processedParams.includeEmptyRows || false; | ||
processedParams.withBOM = processedParams.withBOM || false; | ||
processedOpts.doubleQuote = typeof processedOpts.doubleQuote === 'string' | ||
? processedOpts.doubleQuote | ||
: Array(3).join(processedOpts.quote); | ||
processedOpts.defaultValue = processedOpts.defaultValue; | ||
processedOpts.header = processedOpts.header !== false; | ||
processedOpts.includeEmptyRows = processedOpts.includeEmptyRows || false; | ||
processedOpts.withBOM = processedOpts.withBOM || false; | ||
return processedParams; | ||
return processedOpts; | ||
} | ||
@@ -48,3 +47,3 @@ | ||
getHeader() { | ||
return this.params.fields | ||
return this.opts.fields | ||
.map(field => | ||
@@ -56,7 +55,7 @@ (typeof field === 'string') | ||
.map(header => this.processValue(header, true)) | ||
.join(this.params.delimiter); | ||
.join(this.opts.delimiter); | ||
} | ||
/** | ||
* Preprocess each object according to the give params (unwind, flatten, etc.). | ||
* Preprocess each object according to the give opts (unwind, flatten, etc.). | ||
* | ||
@@ -66,7 +65,7 @@ * @param {Object} row JSON object to be converted in a CSV row | ||
preprocessRow(row) { | ||
const processedRow = (this.params.unwind && this.params.unwind.length) | ||
? this.unwindData(row, this.params.unwind) | ||
const processedRow = (this.opts.unwind && this.opts.unwind.length) | ||
? this.unwindData(row, this.opts.unwind) | ||
: [row]; | ||
if (this.params.flatten) { | ||
return processedRow.map(flatten); | ||
if (this.opts.flatten) { | ||
return processedRow.map(this.flatten); | ||
} | ||
@@ -86,9 +85,9 @@ | ||
|| (Object.getOwnPropertyNames(row).length === 0 | ||
&& !this.params.includeEmptyRows)) { | ||
&& !this.opts.includeEmptyRows)) { | ||
return undefined; | ||
} | ||
return this.params.fields | ||
return this.opts.fields | ||
.map(fieldInfo => this.processCell(row, fieldInfo)) | ||
.join(this.params.delimiter); | ||
.join(this.opts.delimiter); | ||
} | ||
@@ -121,3 +120,3 @@ | ||
? fieldInfo.default | ||
: this.params.defaultValue; | ||
: this.opts.defaultValue; | ||
@@ -190,7 +189,7 @@ let value; | ||
stringifiedValue = stringifiedValue | ||
.replace(/^"(.*)"$/, this.params.quote + '$1' + this.params.quote) | ||
.replace(/(\\")(?=.)/g, this.params.doubleQuote) | ||
.replace(/^"(.*)"$/, this.opts.quote + '$1' + this.opts.quote) | ||
.replace(/(\\")(?=.)/g, this.opts.doubleQuote) | ||
.replace(/\\\\/g, '\\'); | ||
if (this.params.excelStrings && typeof value === 'string') { | ||
if (this.opts.excelStrings && typeof value === 'string') { | ||
stringifiedValue = '"="' + stringifiedValue + '""'; | ||
@@ -203,5 +202,37 @@ } | ||
/** | ||
* Performs the flattening of a data row recursively | ||
* | ||
* @param {Object} dataRow Original JSON object | ||
* @returns {Object} Flattened object | ||
*/ | ||
flatten(dataRow) { | ||
function step (obj, flatDataRow, currentPath) { | ||
Object.keys(obj).forEach((key) => { | ||
const value = obj[key]; | ||
const newPath = currentPath | ||
? `${currentPath}.${key}` | ||
: key; | ||
if (typeof value !== 'object' | ||
|| Array.isArray(value) | ||
|| Object.prototype.toString.call(value.toJSON) === '[object Function]' | ||
|| !Object.keys(value).length) { | ||
flatDataRow[newPath] = value; | ||
return; | ||
} | ||
step(value, flatDataRow, newPath); | ||
}); | ||
return flatDataRow; | ||
} | ||
return step(dataRow, {}); | ||
} | ||
/** | ||
* Performs the unwind recursively in specified sequence | ||
* | ||
* @param {Array} dataRow Original JSON object | ||
* @param {Object} dataRow Original JSON object | ||
* @param {String[]} unwindPaths The paths as strings to be used to deconstruct the array | ||
@@ -208,0 +239,0 @@ * @returns {Array} Array of objects containing all rows after unwind of chosen paths |
@@ -15,15 +15,15 @@ 'use strict'; | ||
if (!this.params.fields) { | ||
if (!this.opts.fields) { | ||
const dataFields = Array.prototype.concat.apply([], | ||
processedData.map(item => Object.keys(item)) | ||
); | ||
this.params.fields = dataFields | ||
this.opts.fields = dataFields | ||
.filter((field, pos, arr) => arr.indexOf(field) == pos); | ||
} | ||
const header = this.params.header ? this.getHeader() : ''; | ||
const header = this.opts.header ? this.getHeader() : ''; | ||
const rows = this.processData(processedData); | ||
const csv = (this.params.withBOM ? '\ufeff' : '') | ||
const csv = (this.opts.withBOM ? '\ufeff' : '') | ||
+ header | ||
+ ((header && rows) ? this.params.eol : '') | ||
+ ((header && rows) ? this.opts.eol : '') | ||
+ rows; | ||
@@ -35,3 +35,3 @@ | ||
/** | ||
* Preprocess the data according to the give params (unwind, flatten, etc.) | ||
* Preprocess the data according to the give opts (unwind, flatten, etc.) | ||
and calculate the fields and field names if they are not provided. | ||
@@ -45,3 +45,3 @@ * | ||
if (processedData.length === 0 || typeof processedData[0] !== 'object') { | ||
throw new Error('params should include "fields" and/or non-empty "data" array of objects'); | ||
throw new Error('Data should not be empty or the "fields" option should be included'); | ||
} | ||
@@ -64,3 +64,3 @@ | ||
.filter(row => row) // Filter empty rows | ||
.join(this.params.eol); | ||
.join(this.opts.eol); | ||
} | ||
@@ -67,0 +67,0 @@ } |
@@ -8,10 +8,10 @@ 'use strict'; | ||
class JSON2CSVTransform extends Transform { | ||
constructor(params) { | ||
super(params); | ||
constructor(opts) { | ||
super(opts); | ||
// Inherit methods from JSON2CSVBase since extends doesn't | ||
// allow multiple inheritance and manually preprocess params | ||
// allow multiple inheritance and manually preprocess opts | ||
Object.getOwnPropertyNames(JSON2CSVBase.prototype) | ||
.forEach(key => (this[key] = JSON2CSVBase.prototype[key])); | ||
this.params = this.preprocessParams(params); | ||
this.opts = this.preprocessOpts(opts); | ||
@@ -21,3 +21,3 @@ this._data = ''; | ||
if (this.params.ndjson) { | ||
if (this.opts.ndjson) { | ||
this.initNDJSONParse(); | ||
@@ -28,3 +28,3 @@ } else { | ||
if (this.params.withBOM) { | ||
if (this.opts.withBOM) { | ||
this.push('\ufeff'); | ||
@@ -88,6 +88,6 @@ } | ||
if (this.stack.length === 0 | ||
&& !transform.params.fields | ||
&& !transform.opts.fields | ||
&& this.mode !== Parser.C.ARRAY | ||
&& this.mode !== Parser.C.OBJECT) { | ||
this.onError(new Error('params should include "fields" and/or non-empty "data" array of objects')); | ||
this.onError(new Error('Data should not be empty or the "fields" option should be included')); | ||
} | ||
@@ -136,5 +136,5 @@ if (this.stack.length === 1) { | ||
if (!this._hasWritten) { | ||
this.params.fields = this.params.fields || Object.keys(processedData[0]); | ||
if (this.params.header) { | ||
const header = this.getHeader(this.params); | ||
this.opts.fields = this.opts.fields || Object.keys(processedData[0]); | ||
if (this.opts.header) { | ||
const header = this.getHeader(this.opts); | ||
this.emit('header', header); | ||
@@ -147,5 +147,5 @@ this.push(header); | ||
processedData.forEach(row => { | ||
const line = this.processRow(row, this.params); | ||
const line = this.processRow(row, this.opts); | ||
if (line === undefined) return; | ||
const eoledLine = (this._hasWritten ? this.params.eol : '') | ||
const eoledLine = (this._hasWritten ? this.opts.eol : '') | ||
+ line; | ||
@@ -152,0 +152,0 @@ this.emit('line', eoledLine); |
{ | ||
"name": "json2csv", | ||
"preferGlobal": "true", | ||
"version": "4.0.0-alpha.1", | ||
"version": "4.0.0-alpha.2", | ||
"description": "Convert JSON to CSV", | ||
@@ -42,6 +42,4 @@ "keywords": [ | ||
"commander": "^2.8.1", | ||
"flat": "^4.0.0", | ||
"jsonparse": "^1.3.1", | ||
"lodash.clonedeep": "^4.5.0", | ||
"lodash.flatten": "^4.4.0", | ||
"lodash.get": "^4.4.0", | ||
@@ -48,0 +46,0 @@ "lodash.set": "^4.3.0" |
@@ -260,4 +260,3 @@ # json2csv | ||
```javascript | ||
const json2csv = require('json2csv'); | ||
const fs = require('fs'); | ||
const Json2csvParser = require('json2csv').Parser; | ||
const fields = ['car', 'price', 'color']; | ||
@@ -279,4 +278,6 @@ const myCars = [ | ||
]; | ||
const csv = json2csv(myCars, { fields }); | ||
const json2csvParser = new Json2csvParser({ fields }); | ||
const csv = json2csvParser.parse(myCars); | ||
console.log(csv); | ||
@@ -299,6 +300,7 @@ ``` | ||
```javascript | ||
const json2csv = require('json2csv'); | ||
const Json2csvParser = require('json2csv').Parser; | ||
const fields = ['car', 'color']; | ||
const csv = json2csv(myCars, { fields }); | ||
const json2csvParser = new Json2csvParser({ fields }); | ||
const csv = json2csvParser.parse(myCars); | ||
@@ -322,3 +324,3 @@ console.log(csv); | ||
```javascript | ||
const json2csv = require('json2csv'); | ||
const Json2csvParser = require('json2csv').Parser; | ||
const fields = [{ | ||
@@ -331,4 +333,6 @@ label: 'Car Name', | ||
}]; | ||
const csv = json2csv(myCars, { fields }); | ||
const json2csvParser = new Json2csvParser({ fields }); | ||
const csv = json2csvParser.parse(myCars, { fields }); | ||
console.log(csv); | ||
@@ -342,4 +346,3 @@ ``` | ||
```javascript | ||
const json2csv = require('json2csv'); | ||
const fs = require('fs'); | ||
const Json2csvParser = require('json2csv').Parser; | ||
const fields = ['car.make', 'car.model', 'price', 'color']; | ||
@@ -361,4 +364,6 @@ const myCars = [ | ||
]; | ||
const csv = json2csv(myCars, { fields }); | ||
const json2csvParser = new Json2csvParser({ fields }); | ||
const csv = json2csvParser.parse(myCars); | ||
console.log(csv); | ||
@@ -378,9 +383,11 @@ ``` | ||
Use a custom delimiter to create tsv files. Add it as the value of the delimiter property on the parameters: | ||
Use a custom delimiter to create tsv files using the delimiter option: | ||
```javascript | ||
const json2csv = require('json2csv'); | ||
const Json2csvParser = require('json2csv').Parser; | ||
const fields = ['car', 'price', 'color']; | ||
const tsv = json2csv(myCars, { fields, delimiter: '\t' }); | ||
const json2csvParser = new Json2csvParser({ fields, delimiter: '\t' }); | ||
const tsv = json2csvParser.parse(myCars); | ||
console.log(tsv); | ||
@@ -406,3 +413,3 @@ ``` | ||
```javascript | ||
const json2csv = require('json2csv'); | ||
const Json2csvParser = require('json2csv').Parser; | ||
const fields = [{ | ||
@@ -415,4 +422,6 @@ label: 'Car Name', | ||
}]; | ||
const csv = json2csv(myCars, { fields, quote: '' }); | ||
const json2csvParser = new Json2csvParser({ fields, quote: '' }); | ||
const csv = json2csvParser.parse(myCars); | ||
console.log(csv); | ||
@@ -435,4 +444,3 @@ ``` | ||
```javascript | ||
const json2csv = require('json2csv'); | ||
const fs = require('fs'); | ||
const Json2csvParser = require('json2csv').Parser; | ||
const fields = ['carModel', 'price', 'colors']; | ||
@@ -458,4 +466,6 @@ const myCars = [ | ||
]; | ||
const csv = json2csv(myCars, { fields, unwind: 'colors' }); | ||
const json2csvParser = new Json2csvParser({ fields, unwind: 'colors' }); | ||
const csv = json2csvParser.parse(myCars); | ||
console.log(csv); | ||
@@ -484,4 +494,3 @@ ``` | ||
```javascript | ||
const json2csv = require('json2csv'); | ||
const fs = require('fs'); | ||
const Json2csvParser = require('json2csv').Parser; | ||
const fields = ['carModel', 'price', 'items.name', 'items.color', 'items.items.position', 'items.items.color']; | ||
@@ -531,4 +540,6 @@ const myCars = [ | ||
]; | ||
const csv = json2csv(myCars, { fields, unwind: ['items', 'items.items'] }); | ||
const json2csvParser = new Json2csvParser({ fields, unwind: ['items', 'items.items'] }); | ||
const csv = json2csvParser.parse(myCars); | ||
console.log(csv); | ||
@@ -549,2 +560,25 @@ ``` | ||
### Migrating from 3.X to 4.X | ||
What in 3.X used to be | ||
``` | ||
const json2csv = require('json2csv'); | ||
const csv = json2csv({ data: myData, fields: myFields, unwindPath: paths, ... }); | ||
``` | ||
can be replaced by | ||
``` | ||
const Json2csvParser = require('json2csv').Parser; | ||
const json2csvParser = new Json2csvParser({ fields: myFields, unwind: paths, ... }); | ||
const csv = json2csvParser.parse(myData); | ||
``` | ||
or the convenience method | ||
``` | ||
const json2csv = require('json2csv'); | ||
const csv = json2csv.parse(myData, { fields: myFields, unwind: paths, ... }); | ||
``` | ||
Please note that many of the configuration parameters have been slightly renamed. Please check one by one that all your parameters are correct. | ||
## Building | ||
@@ -551,0 +585,0 @@ |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
6
2
618
3
358383
14
9896
- Removedflat@^4.0.0
- Removedlodash.flatten@^4.4.0
- Removedflat@4.1.1(transitive)
- Removedis-buffer@2.0.5(transitive)
- Removedlodash.flatten@4.4.0(transitive)