diff --git a/package-lock.json b/package-lock.json index f5e3242..efdec56 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "json-2-csv", - "version": "5.0.0", + "version": "5.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "json-2-csv", - "version": "5.0.0", + "version": "5.0.1", "license": "MIT", "dependencies": { "deeks": "3.0.2", diff --git a/package.json b/package.json index b3284d0..3b63b45 100755 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ }, "name": "json-2-csv", "description": "A JSON to CSV and CSV to JSON converter that natively supports sub-documents and auto-generates the CSV heading.", - "version": "5.0.0", + "version": "5.0.1", "homepage": "https://mrodrig.github.io/json-2-csv", "repository": { "type": "git", diff --git a/src/csv2json.ts b/src/csv2json.ts index 2ca21a2..f95d68d 100644 --- a/src/csv2json.ts +++ b/src/csv2json.ts @@ -154,7 +154,21 @@ export const Csv2Json = function(options: FullCsv2JsonOptions) { stateVariables.startIndex = index + eolDelimiterLength; stateVariables.parsingValue = true; stateVariables.insideWrapDelimiter = charAfter === options.delimiter.wrap; - } else if ((charBefore !== options.delimiter.wrap || stateVariables.justParsedDoubleQuote && charBefore === options.delimiter.wrap) && + } else if (character === options.delimiter.wrap && charBefore === options.delimiter.field && + !stateVariables.insideWrapDelimiter && !stateVariables.parsingValue) { + // If we reached a wrap delimiter after a comma and we aren't inside a wrap delimiter + + stateVariables.startIndex = index; + stateVariables.insideWrapDelimiter = true; + stateVariables.parsingValue = true; + + // If the next character(s) are an EOL delimiter, then skip them so we don't parse what we've seen as another value + if (utils.getNCharacters(csv, index + 1, eolDelimiterLength) === options.delimiter.eol) { + index += options.delimiter.eol.length + 1; // Skip past EOL + } + } + + else if ((charBefore !== options.delimiter.wrap || stateVariables.justParsedDoubleQuote && charBefore === options.delimiter.wrap) && character === options.delimiter.wrap && utils.getNCharacters(csv, index + 1, eolDelimiterLength) === options.delimiter.eol) { // If we reach a wrap which is not preceded by a wrap delim and the next character is an EOL delim (ie. *"\n) @@ -174,13 +188,6 @@ export const Csv2Json = function(options: FullCsv2JsonOptions) { stateVariables.startIndex = index + 2; // next value starts after the field delimiter stateVariables.insideWrapDelimiter = false; stateVariables.parsingValue = false; - } else if (character === options.delimiter.wrap && charBefore === options.delimiter.field && - !stateVariables.insideWrapDelimiter && !stateVariables.parsingValue) { - // If we reached a wrap delimiter after a comma and we aren't inside a wrap delimiter - - stateVariables.startIndex = index; - stateVariables.insideWrapDelimiter = true; - stateVariables.parsingValue = true; } else if (character === options.delimiter.wrap && charBefore === options.delimiter.field && !stateVariables.insideWrapDelimiter && stateVariables.parsingValue) { // If we reached a wrap delimiter with a field delimiter after it (ie. ,"*) diff --git a/test/config/testCsvFilesList.ts b/test/config/testCsvFilesList.ts index 0db426d..634d459 100644 --- a/test/config/testCsvFilesList.ts +++ b/test/config/testCsvFilesList.ts @@ -49,6 +49,7 @@ const csvFileConfig = [ {key: 'quotedFieldWithNewline', file: '../data/csv/quotedFieldWithNewline.csv'}, {key: 'falsyValues', file: '../data/csv/falsyValues.csv'}, {key: 'nestedNotUnwoundObjects', file: '../data/csv/nestedNotUnwoundObjects.csv'}, + {key: 'newlineWithWrapDelimiters', file: '../data/csv/newlineWithWrapDelimiters.csv'}, ]; function readCsvFile(filePath: string) { diff --git a/test/config/testJsonFilesList.ts b/test/config/testJsonFilesList.ts index 30d8e33..6c53836 100644 --- a/test/config/testJsonFilesList.ts +++ b/test/config/testJsonFilesList.ts @@ -41,5 +41,6 @@ export default { nestedDotKeysWithArrayExpandedUnwound: require('../data/json/nestedDotKeysWithArrayExpandedUnwound.json'), emptyColumns: require('../data/json/emptyColumns.json'), quotedFieldWithNewline: require('../data/json/quotedFieldWithNewline.json'), - falsyValues: require('../data/json/falsyValues.json') + falsyValues: require('../data/json/falsyValues.json'), + newlineWithWrapDelimiters: require('../data/json/newlineWithWrapDelimiters'), }; diff --git a/test/csv2json.ts b/test/csv2json.ts index fedc5f8..032d947 100644 --- a/test/csv2json.ts +++ b/test/csv2json.ts @@ -376,6 +376,12 @@ export function runTests() { }); assert.deepEqual(json, expectedJson); }); + + // Test case for issue #240 + it('should handle newline characters properly when inside of a field delimiter', () => { + const json = csv2json(csvTestData.newlineWithWrapDelimiters); + assert.deepEqual(json, jsonTestData.newlineWithWrapDelimiters); + }); }); }); diff --git a/test/data/csv/newlineWithWrapDelimiters.csv b/test/data/csv/newlineWithWrapDelimiters.csv new file mode 100644 index 0000000..0d4e3c2 --- /dev/null +++ b/test/data/csv/newlineWithWrapDelimiters.csv @@ -0,0 +1,3 @@ +"Rating","Feedback","External Id" +"5"," +Layout","id" \ No newline at end of file diff --git a/test/data/json/newlineWithWrapDelimiters.json b/test/data/json/newlineWithWrapDelimiters.json new file mode 100644 index 0000000..a4f935e --- /dev/null +++ b/test/data/json/newlineWithWrapDelimiters.json @@ -0,0 +1,7 @@ +[ + { + "Rating": "5", + "Feedback": "\nLayout", + "External Id": "id" + } +] \ No newline at end of file