Skip to content

Commit 1522385

Browse files
authored
Merge pull request #98 from mrodrig/3.1.0
feature: add emptyFieldValue option
2 parents 4dcdded + b0c57a8 commit 1522385

File tree

10 files changed

+71
-31
lines changed

10 files changed

+71
-31
lines changed

README.md

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,23 @@ Upgrading to v3 from v2? Check out the [upgrade guide](https://github.com/mrodri
4242
* `callback` - A function of the form `function (err, csv)`;
4343
* This function will receive any errors and/or the string of CSV generated.
4444
* `options` - (Optional) A JSON document specifying any of the following key value pairs:
45+
* `checkSchemaDifferences` - Boolean - Should all documents have the same schema?
46+
* Default: `false`
47+
* Note: An error will be thrown if some documents have differing schemas when this is set to `true`.
4548
* `delimiter` - Document - Specifies the different types of delimiters
4649
* `field` - String - Field Delimiter.
4750
* Default: `,`
4851
* `wrap` - String - Wrap values in the delimiter of choice (e.g. wrap values in quotes).
4952
* Default: `"`
5053
* `eol` - String - End of Line Delimiter.
5154
* Default: `\n`
55+
* `emptyFieldValue` - Any - Value that, if specified, will be substituted in for field values that are `undefined`, `null`, or an empty string.
56+
* Default: none
5257
* `excelBOM` - Boolean - Should a unicode character be prepended to allow Excel to open a UTF-8 encoded file with non-ASCII characters present.
58+
* `keys` - Array - Specify the keys (as strings) that should be converted.
59+
* Default: `null`
60+
* If you have a nested object (ie. {info : {name: 'Mike'}}), then set this to ['info.name']
61+
* If you want all keys to be converted, then specify ```null``` or don't specify the option to utilize the default.
5362
* `prependHeader` - Boolean - Should the auto-generated header be prepended as the first line in the CSV?
5463
* Default: `true`
5564
* `sortHeader` - Boolean - Should the header keys be sorted in alphabetical order?
@@ -58,14 +67,6 @@ Upgrading to v3 from v2? Check out the [upgrade guide](https://github.com/mrodri
5867
* Default: `false`
5968
* `trimFieldValues` - Boolean - Should the field values be trimmed? (*in development*)
6069
* Default: `false`
61-
* `checkSchemaDifferences` - Boolean - Should all documents have the same schema?
62-
* Default: `false`
63-
* Note: Change this to `false` if some documents are missing certain fields and you still want to convert the data.
64-
* `keys` - Array - Specify the keys (as strings) that should be converted.
65-
* Default: `null`
66-
* If you have a nested object (ie. {info : {name: 'Mike'}}), then set this to ['info.name']
67-
* If you want all keys to be converted, then specify ```null``` or don't specify the option to utilize the default.
68-
6970

7071

7172
For examples, please refer to the [json2csv API Documentation (Link)](https://github.com/mrodrig/json-2-csv/wiki/json2csv-Documentation)
@@ -87,15 +88,15 @@ Available in version `2.2.0`, this functionality makes use of promises from the
8788
* `eol` - String - End of Line Delimiter.
8889
* Default: `\n`
8990
* `excelBOM` - Boolean - Does the CSV contain a unicode character prepended in order to allow Excel to open a UTF-8 encoded file with non-ASCII characters present?
90-
* Default: `false`
91-
* `trimHeaderFields` - Boolean - Should the header fields be trimmed?
92-
* Default: `false`
93-
* `trimFieldValues` - Boolean - Should the field values be trimmed?
9491
* Default: `false`
9592
* `keys` - Array - Specify the keys (as strings) that should be converted.
9693
* Default: `null`
9794
* If you have a nested object (ie. `{info : {name: 'Mike'}}`), then set this to `['info.name']`
9895
* If you want all keys to be converted, then specify `null` or don't specify the option to utilize the default.
96+
* `trimHeaderFields` - Boolean - Should the header fields be trimmed?
97+
* Default: `false`
98+
* `trimFieldValues` - Boolean - Should the field values be trimmed?
99+
* Default: `false`
99100

100101
For examples, please refer to the [csv2json API Documentation (Link)](https://github.com/mrodrig/json-2-csv/wiki/csv2json-Documentation)
101102

@@ -109,18 +110,16 @@ Available in version `2.2.0`, this functionality makes use of promises from the
109110
$ npm test
110111
```
111112

112-
_Note_: This requires `mocha`, `should`, and `underscore`.
113-
114113
To see test coverage, please run:
115114
```bash
116115
$ npm run coverage
117116
```
118117

119118
Current Coverage is:
120119
```
121-
Statements : 100% ( 258/258 )
122-
Branches : 100% ( 124/124 )
123-
Functions : 100% ( 49/49 )
120+
Statements : 100% ( 261/261 )
121+
Branches : 100% ( 131/131 )
122+
Functions : 100% ( 47/47 )
124123
Lines : 100% ( 256/256 )
125124
```
126125

@@ -130,13 +129,12 @@ Please find the updated list (relocated to the Wiki) here: [Frequently Asked Que
130129
## Features
131130
* Header Generation (per document keys)
132131
* Allows for conversion of specific keys in both json2csv and csv2json via the options.keys parameter (as of 1.1.2)
133-
* Verifies all documents have same schema (schema field order does not matter as of 1.1.0)
132+
* Document schema verification functionality (field order is irrelevant) (as of 1.1.0)
134133
* Supports sub-documents natively
135134
* Supports arrays as document values for both json2csv and csv2json
136135
* Custom ordering of columns (see F.A.Q. for more information)
137136
* Ability to re-generate the JSON documents that were used to generate the CSV (including nested documents)
138137
* Allows for custom field delimiters, end of line delimiters, etc.
139-
* Promisifiable via bluebird's .promisify(<function>) and .promisifyAll(<object>) (as of 1.1.1)
140138
* Wrapped value support for json2csv and csv2json (as of 1.3.0)
141139
* Support for multiple different schemas (as of 1.4.0)
142140
* Promisified versions of the functions are now available by default: json2csvAsync, csv2jsonAsync (as of 2.2.0)
@@ -145,3 +143,4 @@ Please find the updated list (relocated to the Wiki) here: [Frequently Asked Que
145143
* `csv2json test.csv -o output.json`
146144
* *and*
147145
* `json2csv test.json -o output.csv -W -k arrayOfStrings -o output.csv`
146+
* Empty field value option (as of 3.1.0)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"author": "mrodrig",
33
"name": "json-2-csv",
44
"description": "A JSON to CSV and CSV to JSON converter that natively supports sub-documents and auto-generates the CSV heading.",
5-
"version": "3.0.0",
5+
"version": "3.1.0",
66
"repository": {
77
"type": "git",
88
"url": "http://github.com/mrodrig/json-2-csv.git"

src/json2csv.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ const Json2Csv = function(options) {
193193

194194
fields.forEach((field) => {
195195
let recordFieldValue = path.evaluatePath(record, field);
196+
197+
if (!_.isUndefined(options.emptyFieldValue) && utils.isEmptyField(recordFieldValue)) {
198+
recordFieldValue = options.emptyFieldValue;
199+
}
200+
196201
recordValues.push(recordFieldValue);
197202
});
198203

src/utils.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ module.exports = {
1010
isDateRepresentation,
1111
computeSchemaDifferences,
1212
deepCopy,
13-
convert
13+
convert,
14+
isEmptyField
1415
};
1516

1617
/**
@@ -127,3 +128,13 @@ function computeSchemaDifferences(schemaA, schemaB) {
127128
return _.difference(schemaA, schemaB)
128129
.concat(_.difference(schemaB, schemaA));
129130
}
131+
132+
/**
133+
* Utility function to check if a field is considered empty so that the emptyFieldValue can be used instead
134+
* @param fieldValue
135+
* @returns {boolean}
136+
*/
137+
function isEmptyField(fieldValue) {
138+
console.log(fieldValue);
139+
return _.isUndefined(fieldValue) || _.isNull(fieldValue) || fieldValue === '';
140+
}

test/config/testCsvFilesList.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ const fs = require('fs'),
2323
{key: 'specifiedKeys', file: '../data/csv/specifiedKeys.csv'},
2424
{key: 'extraLine', file: '../data/csv/extraLine.csv'},
2525
{key: 'noHeader', file: '../data/csv/noHeader.csv'},
26-
{key: 'sortedHeader', file: '../data/csv/sortedHeader.csv'}
26+
{key: 'sortedHeader', file: '../data/csv/sortedHeader.csv'},
27+
{key: 'emptyFieldValues', file: '../data/csv/emptyFieldValues.csv'}
2728
];
2829

2930
function readCsvFile(filePath) {

test/config/testJsonFilesList.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ module.exports = {
1616
trimmedFields: require('../data/json/trimmedFields'),
1717
trimHeader: require('../data/json/trimHeader'),
1818
trimmedHeader: require('../data/json/trimmedHeader'),
19-
specifiedKeys: require('../data/json/specifiedKeys')
19+
specifiedKeys: require('../data/json/specifiedKeys'),
20+
emptyFieldValues: require('../data/json/emptyFieldValues')
2021
};

test/data/csv/emptyFieldValues.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
arrayOfStrings,object.subField,isBoolean,optionalField,number
2+
"[""test1"",""test2""]",,true,this one has it,
3+
"[""test3"",""test4""]",subValue,false,,7

test/data/json/emptyFieldValues.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module.exports = [
2+
{
3+
arrayOfStrings: ['test1', 'test2'],
4+
object: { subField: '' },
5+
number: undefined,
6+
isBoolean: true,
7+
optionalField: 'this one has it'
8+
},
9+
{
10+
arrayOfStrings: ['test3', 'test4'],
11+
object: { subField: 'subValue' },
12+
number: 7,
13+
isBoolean: false,
14+
optionalField: null
15+
}
16+
];

test/json2csv.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,17 @@ function runTests(jsonTestData, csvTestData) {
343343
keys: ['arrayOfStrings', 'object.subField']
344344
});
345345
});
346+
347+
it('should use the specified empty field value, if provided', (done) => {
348+
jsonTestData.emptyFieldValues[0].number = undefined;
349+
converter.json2csv(jsonTestData.emptyFieldValues, (err, csv) => {
350+
if (err) done(err);
351+
csv.should.equal(csvTestData.emptyFieldValues);
352+
done();
353+
}, {
354+
emptyFieldValue: ''
355+
});
356+
});
346357
});
347358
});
348359

upgrade_guides/UPGRADE_2_to_3.md

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ available, however, you will need to update your code to use the new keys.
1212
The following lists the key name changes (left = old, right = new)
1313

1414
```
15-
EMPTY_FIELD_VALUE --> * REMOVED *
15+
EMPTY_FIELD_VALUE --> emptyFieldValue
1616
CHECK_SCHEMA_DIFFERENCES --> checkSchemaDifferences
1717
KEYS --> keys
1818
PARSE_CSV_NUMBERS --> parseCsvNumbers
@@ -36,13 +36,6 @@ This was likely one of the least commonly used options and instead became a pain
3636
point since the array delimiter was required to be different from the field
3737
delimiter prior to v3.0.0.
3838

39-
* Empty Field Value Option Removed
40-
41-
The empty field value option was previously not being used by the json2csv
42-
function, so for simplicity, it has been removed in v3.0.0. Please open an issue
43-
on the GitHub repository `mrodrig/json-2-csv` if you have a valid use case for
44-
this option to be implemented.
45-
4639
* Schema Difference Check
4740

4841
By default, the schema difference check for `json2csv` has now been disabled.

0 commit comments

Comments
 (0)