Skip to content

Commit

Permalink
Merge branch 'master' into improvement/remove_fieldNames
Browse files Browse the repository at this point in the history
  • Loading branch information
knownasilya authored Jan 23, 2018
2 parents e7fbc79 + 2096ade commit d00afdb
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 317 deletions.
53 changes: 27 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,11 @@ try {
- `header` - Boolean, determines whether or not CSV file will contain a title column. Defaults to `true` if not specified.
- `eol` - String, overrides the default OS line ending (i.e. `\n` on Unix and `\r\n` on Windows).
- `flatten` - Boolean, flattens nested JSON using [flat]. Defaults to `false`.
- `unwindPath` - Array of Strings, creates multiple rows from a single JSON document similar to MongoDB's $unwind
- `unwind` - Array of Strings, creates multiple rows from a single JSON document similar to MongoDB's $unwind
- `excelStrings` - Boolean, converts string data into normalized Excel style data.
- `includeEmptyRows` - Boolean, includes empty rows. Defaults to `false`.
- `preserveNewLinesInValues` - Boolean, preserve \r and \n in values. Defaults to `false`.
- `withBOM` - Boolean, with BOM character. Defaults to `false`.
- `callback` - `function (error, csvString) {}`. If provided, will callback asynchronously. Only supported for compatibility reasons.

#### Example `fields` option
``` javascript
Expand Down Expand Up @@ -143,16 +142,14 @@ car, price, color
### Example 2

Similarly to [mongoexport](http://www.mongodb.org/display/DOCS/mongoexport) you can choose which fields to export.
Note: this example uses the optional callback format.

```javascript
var json2csv = require('json2csv');
var fields = ['car', 'color'];

json2csv({ data: myCars, fields: fields }, function(err, csv) {
if (err) console.log(err);
console.log(csv);
});
var csv = json2csv({ data: myCars, fields: fields });

console.log(csv);
```

Results in
Expand Down Expand Up @@ -274,7 +271,7 @@ car.make, car.model, price, color

### Example 7

You can unwind arrays similar to MongoDB's $unwind operation using the `unwindPath` option.
You can unwind arrays similar to MongoDB's $unwind operation using the `unwind` option.

```javascript
var json2csv = require('json2csv');
Expand All @@ -299,7 +296,7 @@ var myCars = [
"colors": ["green","teal","aqua"]
}
];
var csv = json2csv({ data: myCars, fields: fields, unwindPath: 'colors' });
var csv = json2csv({ data: myCars, fields: fields, unwind: 'colors' });

fs.writeFile('file.csv', csv, function(err) {
if (err) throw err;
Expand Down Expand Up @@ -373,7 +370,7 @@ var myCars = [
]
}
];
var csv = json2csv({ data: myCars, fields: fields, unwindPath: ['items', 'items.items'] });
var csv = json2csv({ data: myCars, fields: fields, unwind: ['items', 'items.items'] });

fs.writeFile('file.csv', csv, function(err) {
if (err) throw err;
Expand Down Expand Up @@ -402,22 +399,26 @@ Usage: json2csv [options]

Options:

-h, --help output usage information
-V, --version output the version number
-i, --input <input> Path and name of the incoming json file.
-o, --output [output] Path and name of the resulting csv file. Defaults to console.
-f, --fields <fields> Specify the fields to convert.
-l, --fieldList [list] Specify a file with a list of fields to include. One field per line.
-d, --delimiter [delimiter] Specify a delimiter other than the default comma to use.
-e, --eol [value] Specify an End-of-Line value for separating rows.
-q, --quote [value] Specify an alternate quote value.
-n, --no-header Disable the column name header
-F, --flatten Flatten nested objects
-u, --unwindPath <paths> Creates multiple rows from a single JSON document similar to MongoDB unwind.
-L, --ldjson Treat the input as Line-Delimited JSON.
-p, --pretty Use only when printing to console. Logs output in pretty tables.
-a, --include-empty-rows Includes empty rows in the resulting CSV output.
-b, --with-bom Includes BOM character at the beginning of the CSV.
-h, --help output usage information
-V, --version output the version number
-i, --input <input> Path and name of the incoming json file. If not provided, will read from stdin.
-o, --output [output] Path and name of the resulting csv file. Defaults to stdout.
-f, --fields <fields> Specify the fields to convert.
-l, --fieldList [list] Specify a file with a list of fields to include. One field per line.
-d, --delimiter [delimiter] Specify a delimiter other than the default comma to use.
-v, --default-value [defaultValue] Specify a default value other than empty string.
-e, --eol [value] Specify an End-of-Line value for separating rows.
-q, --quote [value] Specify an alternate quote value.
-dq, --double-quotes [value] Specify a value to replace double quote in strings
-ex, --excel-strings Converts string data into normalized Excel style data
-n, --no-header Disable the column name header
-F, --flatten Flatten nested objects
-u, --unwind <paths> Creates multiple rows from a single JSON document similar to MongoDB unwind.
-L, --ldjson Treat the input as Line-Delimited JSON.
-p, --pretty Use only when printing to console. Logs output in pretty tables.
-a, --include-empty-rows Includes empty rows in the resulting CSV output.
-b, --with-bom Includes BOM character at the beginning of the csv.
-h, --help output usage information
```

An input file `-i` and fields `-f` are required. If no output `-o` is specified the result is logged to the console.
Expand Down
14 changes: 8 additions & 6 deletions bin/json2csv.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ program
.option('-i, --input <input>', 'Path and name of the incoming json file. If not provided, will read from stdin.')
.option('-o, --output [output]', 'Path and name of the resulting csv file. Defaults to stdout.')
.option('-f, --fields <fields>', 'Specify the fields to convert.')
.option('-l, --fieldList [list]', 'Specify a file with a list of fields to include. One field per line.')
.option('-l, --field-list [list]', 'Specify a file with a list of fields to include. One field per line.')
.option('-d, --delimiter [delimiter]', 'Specify a delimiter other than the default comma to use.')
.option('-v, --defaultValue [defaultValue]', 'Specify a default value other than empty string.')
.option('-v, --default-value [defaultValue]', 'Specify a default value other than empty string.')
.option('-e, --eol [value]', 'Specify an End-of-Line value for separating rows.')
.option('-q, --quote [value]', 'Specify an alternate quote value.')
.option('-dq, --doubleQuotes [value]', 'Specify a value to replace double quote in strings')
.option('-dq, --double-quotes [value]', 'Specify a value to replace double quote in strings')
.option('-ex, --excel-strings','Converts string data into normalized Excel style data')
.option('-n, --no-header', 'Disable the column name header')
.option('-F, --flatten', 'Flatten nested objects')
.option('-u, --unwindPath <paths>', 'Creates multiple rows from a single JSON document similar to MongoDB unwind.')
.option('-u, --unwind <paths>', 'Creates multiple rows from a single JSON document similar to MongoDB unwind.')
.option('-L, --ldjson', 'Treat the input as Line-Delimited JSON.')
.option('-p, --pretty', 'Use only when printing to console. Logs output in pretty tables.')
.option('-a, --include-empty-rows', 'Includes empty rows in the resulting CSV output.')
Expand Down Expand Up @@ -123,6 +124,7 @@ getFields(function (err, fields) {
quote: program.quote,
doubleQuotes: program.doubleQuotes,
defaultValue: program.defaultValue,
excelStrings: program.excelStrings,
flatten: program.flatten,
includeEmptyRows: program.includeEmptyRows,
withBOM: program.withBom
Expand All @@ -136,8 +138,8 @@ getFields(function (err, fields) {
opts.eol = program.eol;
}

if (program.unwindPath) {
opts.unwindPath = program.unwindPath.split(',');
if (program.unwind) {
opts.unwind = program.unwind.split(',');
}

var csv = json2csv(opts);
Expand Down
2 changes: 1 addition & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ declare namespace json2csv {
header?: boolean;
eol?: string;
flatten?: boolean;
unwindPath?: string | string[];
unwind?: string | string[];
excelStrings?: boolean;
includeEmptyRows?: boolean;
preserveNewLinesInValues?: boolean;
Expand Down
63 changes: 21 additions & 42 deletions lib/json2csv.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var flatten = require('flat');
* @property {Boolean} [header=true] - determines whether or not CSV file will contain a title column
* @property {String} [eol=''] - overrides the default OS line ending (\n on Unix \r\n on Windows)
* @property {Boolean} [flatten=false] - flattens nested JSON using flat (https://www.npmjs.com/package/flat)
* @property {String[]} [unwindPath] - similar to MongoDB's $unwind, Deconstructs an array field from the input JSON to output a row for each element
* @property {String[]} [unwind] - similar to MongoDB's $unwind, Deconstructs an array field from the input JSON to output a row for each element
* @property {Boolean} [excelStrings] - converts string data into normalized Excel style data
* @property {Boolean} [includeEmptyRows=false] - includes empty rows
* @property {Boolean} [withBOM=false] - includes BOM character at the beginning of the csv
Expand All @@ -30,38 +30,17 @@ var flatten = require('flat');
/**
* Main function that converts json to csv.
*
* @param {Json2CsvParams} params Function parameters containing data, fields,
* delimiter (default is ','), header (default is true)
* and default value (default is '')
* @param {Function} [callback] Callback function
* if error, returning error in call back.
* if csv is created successfully, returning csv output to callback.
* @param {Json2CsvParams} params parameters containing data and
* and options to configure how that data is processed.
* @returns {String} The CSV formated data as a string
*/
module.exports = function (params, callback) {
var hasCallback = typeof callback === 'function';

try {
checkParams(params);
} catch (err) {
if (hasCallback) {
return process.nextTick(function () {
callback(err);
});
} else {
throw err;
}
}
module.exports = function (params) {
checkParams(params);

var titles = createColumnTitles(params);
var csv = createColumnContent(params, titles);

if (hasCallback) {
return process.nextTick(function () {
callback(null, csv);
});
} else {
return csv;
}
return csv;
};


Expand Down Expand Up @@ -131,12 +110,12 @@ function checkParams(params) {
// check with BOM, defaults to false
params.withBOM = params.withBOM || false;

// check unwindPath, defaults to empty array
params.unwindPath = params.unwindPath || [];
// check unwind, defaults to empty array
params.unwind = params.unwind || [];

// if unwindPath is not in array [{}], then just create 1 item array.
if (!Array.isArray(params.unwindPath)) {
params.unwindPath = [params.unwindPath];
// if unwind is not in array [{}], then just create 1 item array.
if (!Array.isArray(params.unwind)) {
params.unwind = [params.unwind];
}
}

Expand Down Expand Up @@ -195,7 +174,7 @@ function replaceQuotationMarks(stringifiedElement, quote) {
* @returns {String} csv string
*/
function createColumnContent(params, str) {
createDataRows(params.data, params.unwindPath).forEach(function (dataElement) {
createDataRows(params.data, params.unwind).forEach(function (dataElement) {
// if null do nothing, if empty object without includeEmptyRows do nothing
if (dataElement && (Object.getOwnPropertyNames(dataElement).length > 0 || params.includeEmptyRows)) {
var line = '';
Expand Down Expand Up @@ -302,7 +281,7 @@ function createColumnContent(params, str) {
* Performs the unwind recursively in specified sequence
*
* @param {Array} originalData The params.data value. Original array of JSON objects
* @param {String[]} unwindPaths The params.unwindPath value. Unwind strings to be used to deconstruct array
* @param {String[]} unwindPaths The params.unwind value. Unwind strings to be used to deconstruct array
* @returns {Array} Array of objects containing all rows after unwind of chosen paths
*/
function createDataRows(originalData, unwindPaths) {
Expand All @@ -312,8 +291,8 @@ function createDataRows(originalData, unwindPaths) {
originalData.forEach(function (dataElement) {
var dataRow = [dataElement];

unwindPaths.forEach(function (unwindPath) {
dataRow = unwindRows(dataRow, unwindPath);
unwindPaths.forEach(function (unwind) {
dataRow = unwindRows(dataRow, unwind);
});

Array.prototype.push.apply(dataRows, dataRow);
Expand All @@ -329,25 +308,25 @@ function createDataRows(originalData, unwindPaths) {
* Performs the unwind logic if necessary to convert single JSON document into multiple rows
*
* @param {Array} inputRows Array contaning single or multiple rows to unwind
* @param {String} unwindPath Single path to do unwind
* @param {String} unwind Single path to do unwind
* @returns {Array} Array of rows processed
*/
function unwindRows(inputRows, unwindPath) {
function unwindRows(inputRows, unwind) {
var outputRows = [];

inputRows.forEach(function (dataEl) {
var unwindArray = lodashGet(dataEl, unwindPath);
var unwindArray = lodashGet(dataEl, unwind);
var isArr = Array.isArray(unwindArray);

if (isArr && unwindArray.length) {
unwindArray.forEach(function (unwindEl) {
var dataCopy = lodashCloneDeep(dataEl);
lodashSet(dataCopy, unwindPath, unwindEl);
lodashSet(dataCopy, unwind, unwindEl);
outputRows.push(dataCopy);
});
} else if (isArr && !unwindArray.length) {
var dataCopy = lodashCloneDeep(dataEl);
lodashSet(dataCopy, unwindPath, undefined);
lodashSet(dataCopy, unwind, undefined);
outputRows.push(dataCopy);
} else {
outputRows.push(dataEl);
Expand Down
Loading

0 comments on commit d00afdb

Please sign in to comment.