From d5099635128d5bc4af3a7f05dca01cff6b80ee98 Mon Sep 17 00:00:00 2001 From: Nick Babcock Date: Tue, 20 Dec 2016 09:52:22 -0500 Subject: [PATCH] Add trailing comma feature Currently the behavior allows there to be a single extraneous data column that is empty. This is normally harmless, however, external tools that expect the same number of data columns as header columns will complain when this extraneous column is encountered. The fix is to make this feature explicit and allow for it to be disabled. This patch retains backwards compatibility by enabling the feature by default. --- .../jackson/dataformat/csv/CsvParser.java | 11 +++++- .../csv/deser/TrailingCommaTest.java | 39 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TrailingCommaTest.java diff --git a/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvParser.java b/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvParser.java index 33480eb..7c2d0f5 100644 --- a/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvParser.java +++ b/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvParser.java @@ -67,6 +67,15 @@ public enum Feature * @since 2.7 */ IGNORE_TRAILING_UNMAPPABLE(false), + + /** + * Feature that allows there to be a trailing single extraneous data + * column that is empty. When this feature is disabled, any extraneous + * column, regardless of content will cause an exception to be thrown. + * Disabling this feature is only useful when + * IGNORE_TRAILING_UNMAPPABLE is also disabled. + */ + ALLOW_TRAILING_COMMA(true), ; final boolean _defaultState; @@ -730,7 +739,7 @@ protected JsonToken _handleExtraColumn(String value) throws IOException // 14-Mar-2012, tatu: As per [dataformat-csv#1], let's allow one specific case // of extra: if we get just one all-whitespace entry, that can be just skipped _state = STATE_SKIP_EXTRA_COLUMNS; - if (_columnIndex == _columnCount) { + if (_columnIndex == _columnCount && Feature.ALLOW_TRAILING_COMMA.enabledIn(_formatFeatures)) { value = value.trim(); if (value.isEmpty()) { // if so, need to verify we then get the end-of-record; diff --git a/src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TrailingCommaTest.java b/src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TrailingCommaTest.java new file mode 100644 index 0000000..9192c19 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TrailingCommaTest.java @@ -0,0 +1,39 @@ +package com.fasterxml.jackson.dataformat.csv.deser; + +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.MappingIterator; +import com.fasterxml.jackson.dataformat.csv.CsvMapper; +import com.fasterxml.jackson.dataformat.csv.CsvParser; +import com.fasterxml.jackson.dataformat.csv.CsvSchema; +import com.fasterxml.jackson.dataformat.csv.ModuleTestBase; + +public class TrailingCommaTest extends ModuleTestBase { + final CsvMapper MAPPER = mapperForCsv(); + + @JsonPropertyOrder({ "a", "b" }) + static class StringPair { + public String a, b; + } + + public void testDisallowTrailingComma() throws Exception + { + final String INPUT = "s,t\nd,e,\n"; + final CsvSchema schema = MAPPER.schemaFor(StringPair.class); + + MappingIterator it = MAPPER.readerFor(StringPair.class) + .with(schema) + .without(CsvParser.Feature.ALLOW_TRAILING_COMMA) + .readValues(INPUT); + + it.nextValue(); + try { + it.nextValue(); + fail("Should not have passed"); + } catch (JsonMappingException e) { + verifyException(e, "Too many entries: expected at most 2 (value #2 (0 chars) \"\")"); + } + + it.close(); + } +}