Skip to content

Commit 8062ef2

Browse files
authored
Merge pull request #246 from mrodrig/feat/improved-excludeKeys-matching
Feat/improved exclude keys matching
2 parents 7b32338 + e18d66c commit 8062ef2

File tree

7 files changed

+84
-2
lines changed

7 files changed

+84
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Returns the CSV `string` or rejects with an `Error` if there was an issue.
6363
* `emptyFieldValue` - Any - Value that, if specified, will be substituted in for field values that are `undefined`, `null`, or an empty string.
6464
* Default: none
6565
* `excelBOM` - Boolean - Should a unicode character be prepended to allow Excel to open a UTF-8 encoded file with non-ASCII characters present.
66-
* `excludeKeys` - Array - Specify the keys that should be excluded from the output.
66+
* `excludeKeys` - Array - Specify the keys that should be excluded from the output. Provided keys will also be used as a RegExp to help exclude keys under a specified prefix, such as all keys of Objects in an Array when `expandArrayObjects` is `true`.
6767
* Default: `[]`
6868
* Note: When used with `unwindArrays`, arrays present at excluded key paths will not be unwound.
6969
* `expandNestedObjects` - Boolean - Should nested objects be deep-converted to CSV?

src/json2csv.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,15 @@ export const Json2Csv = function(options: FullJson2CsvOptions) {
8282
function filterExcludedKeys(keyPaths: string[]) {
8383
if (options.excludeKeys) {
8484
return keyPaths.filter((keyPath) => {
85-
return !options.excludeKeys.includes(keyPath);
85+
for (const excludedKey of options.excludeKeys) {
86+
// Only match if the excludedKey appears at the beginning of the string so we don't accidentally match a key farther down in a key path
87+
const regex = new RegExp(`^${excludedKey}`);
88+
89+
if (excludedKey === keyPath || keyPath.match(regex)) {
90+
return false; // Exclude the key
91+
}
92+
}
93+
return true; // Otherwise, include the key
8694
});
8795
}
8896

test/config/testCsvFilesList.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const csvFileConfig = [
5050
{key: 'falsyValues', file: '../data/csv/falsyValues.csv'},
5151
{key: 'nestedNotUnwoundObjects', file: '../data/csv/nestedNotUnwoundObjects.csv'},
5252
{key: 'newlineWithWrapDelimiters', file: '../data/csv/newlineWithWrapDelimiters.csv'},
53+
{key: 'excludeKeyPattern', file: '../data/csv/excludeKeyPattern.csv'},
5354
];
5455

5556
function readCsvFile(filePath: string) {

test/config/testJsonFilesList.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ export default {
4343
quotedFieldWithNewline: require('../data/json/quotedFieldWithNewline.json'),
4444
falsyValues: require('../data/json/falsyValues.json'),
4545
newlineWithWrapDelimiters: require('../data/json/newlineWithWrapDelimiters'),
46+
excludeKeyPattern: require('../data/json/excludeKeyPattern'),
4647
};

test/data/csv/excludeKeyPattern.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
id,name.arr
2+
1,this should appear
3+
2,this should also appear

test/data/json/excludeKeyPattern.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[
2+
{
3+
"id": 1,
4+
"arr": [
5+
{
6+
"name": "foo"
7+
}
8+
],
9+
"name": {
10+
"arr": "this should appear"
11+
}
12+
},
13+
{
14+
"id": 2,
15+
"arr": [
16+
{
17+
"name": "bar"
18+
}
19+
],
20+
"name": {
21+
"arr": "this should also appear"
22+
}
23+
}
24+
]

test/json2csv.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,51 @@ export function runTests() {
478478
assert.equal(csv, updatedCsv);
479479
});
480480

481+
// Test case for #244
482+
it('should exclude a matched key prefix from the output when unwinding arrays', () => {
483+
const updatedCsv = csvTestData.unwind.replace(',data.options.name', '')
484+
.replace(/,MacBook (Pro|Air) \d+/g, '')
485+
.replace(/,(Super|Turbo)charger/g, '')
486+
.replace('5cf7ca3616c91100018844af,Computers\n', '')
487+
// Remove duplicate lines
488+
.replace('5cf7ca3616c91100018844bf,Cars\n', '');
489+
490+
const csv = json2csv(jsonTestData.unwind, {
491+
unwindArrays: true,
492+
expandArrayObjects: true,
493+
excludeKeys: ['data.options']
494+
});
495+
496+
assert.equal(csv, updatedCsv);
497+
});
498+
499+
// Test case for #244
500+
it('should exclude a matched key prefix from the output when unwinding arrays', () => {
501+
const updatedCsv = csvTestData.unwind.replace(',data.category,data.options.name', '')
502+
.replace(/,Computers,MacBook (Pro|Air) \d+/g, '')
503+
.replace(/,Cars,(Super|Turbo)charger/g, '')
504+
.replace('5cf7ca3616c91100018844af\n', '')
505+
// Remove duplicate lines
506+
.replace('5cf7ca3616c91100018844bf\n', '');
507+
508+
const csv = json2csv(jsonTestData.unwind, {
509+
unwindArrays: true,
510+
excludeKeys: ['data']
511+
});
512+
513+
assert.equal(csv, updatedCsv);
514+
});
515+
516+
// Test case for #244
517+
it('should exclude a matched key prefix, but not if it is not at the start of the key path', () => {
518+
const csv = json2csv(jsonTestData.excludeKeyPattern, {
519+
expandArrayObjects: true,
520+
excludeKeys: ['arr']
521+
});
522+
523+
assert.equal(csv, csvTestData.excludeKeyPattern);
524+
});
525+
481526
it('should use a custom value parser function when provided', () => {
482527
const updatedCsv = csvTestData.trimmedFields.split('\n');
483528
const textRow = 'Parsed Value,Parsed Value,Parsed Value,Parsed Value,Parsed Value';

0 commit comments

Comments
 (0)