From c13b0d59f97d81e78f2f919977f257daa5d3bef1 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Sat, 11 Jul 2020 15:17:01 -0700 Subject: [PATCH] Backport #204 fix to 2.10(.5) --- .../jackson/dataformat/csv/CsvParser.java | 7 +++- .../jackson/dataformat/csv/CsvSchema.java | 20 ++++++++- ...mmaTest.java => TrailingCommaCSVTest.java} | 42 +++++++++++++++++-- release-notes/VERSION-2.x | 4 +- 4 files changed, 66 insertions(+), 7 deletions(-) rename csv/src/test/java/com/fasterxml/jackson/dataformat/csv/deser/{TrailingCommaTest.java => TrailingCommaCSVTest.java} (52%) diff --git a/csv/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvParser.java b/csv/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvParser.java index d6de7633..cf25d1da 100644 --- a/csv/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvParser.java +++ b/csv/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvParser.java @@ -756,7 +756,6 @@ protected void _readHeaderLine() throws IOException { while ((name = _reader.nextString()) != null) { // one more thing: always trim names, regardless of config settings name = name.trim(); - // See if "old" schema defined type; if so, use that type... CsvSchema.Column prev = _schema.column(name); if (prev != null) { @@ -769,6 +768,11 @@ protected void _readHeaderLine() throws IOException { } } + // [dataformats-text#204]: Drop trailing empty name if so instructed + if (CsvParser.Feature.ALLOW_TRAILING_COMMA.enabledIn(_formatFeatures)) { + builder.dropLastColumnIfEmpty(); + } + // Ok: did we get any columns? CsvSchema newSchema = builder.build(); int size = newSchema.size(); @@ -995,6 +999,7 @@ protected JsonToken _handleExtraColumn(String value) throws IOException if (next == null) { // should end of record or input return _handleObjectRowEnd(); } + System.err.println("... yet we did NOT skip"); } } // 21-May-2015, tatu: Need to enter recovery mode, to skip remainder of the line diff --git a/csv/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvSchema.java b/csv/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvSchema.java index 681b7ec3..9e7fdb2f 100644 --- a/csv/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvSchema.java +++ b/csv/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvSchema.java @@ -558,6 +558,22 @@ public Builder renameColumn(int index, String newName) { return this; } + /** + * Helper method called to drop the last collected column name if + * it is empty: called if {link CsvParser.Feature#ALLOW_TRAILING_COMMA} + * enabled to remove the last entry after being added initially. + * + * @since 2.11.2 + */ + public void dropLastColumnIfEmpty() { + final int ix = _columns.size() - 1; + if (ix >= 0) { + if (_columns.get(ix).getName().isEmpty()) { + _columns.remove(ix); + } + } + } + public Builder setColumnType(int index, ColumnType type) { _checkIndex(index); _columns.set(index, _columns.get(index).withType(type)); @@ -795,7 +811,7 @@ public Builder setNullValue(char[] nvl) { _nullValue = nvl; return this; } - + public CsvSchema build() { Column[] cols = _columns.toArray(new Column[_columns.size()]); @@ -817,7 +833,7 @@ protected void _checkIndex(int index) { /* Configuration, construction /********************************************************************** */ - + /** * Column definitions, needed for optional header and/or mapping * of field names to column positions. diff --git a/csv/src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TrailingCommaTest.java b/csv/src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TrailingCommaCSVTest.java similarity index 52% rename from csv/src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TrailingCommaTest.java rename to csv/src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TrailingCommaCSVTest.java index 9192c19f..81d6d367 100644 --- a/csv/src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TrailingCommaTest.java +++ b/csv/src/test/java/com/fasterxml/jackson/dataformat/csv/deser/TrailingCommaCSVTest.java @@ -1,5 +1,7 @@ package com.fasterxml.jackson.dataformat.csv.deser; +import java.util.List; + import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.MappingIterator; @@ -8,14 +10,20 @@ import com.fasterxml.jackson.dataformat.csv.CsvSchema; import com.fasterxml.jackson.dataformat.csv.ModuleTestBase; -public class TrailingCommaTest extends ModuleTestBase { - final CsvMapper MAPPER = mapperForCsv(); - +public class TrailingCommaCSVTest extends ModuleTestBase +{ @JsonPropertyOrder({ "a", "b" }) static class StringPair { public String a, b; } + static class Person { + public String name; + public int age; + } + + private final CsvMapper MAPPER = mapperForCsv(); + public void testDisallowTrailingComma() throws Exception { final String INPUT = "s,t\nd,e,\n"; @@ -36,4 +44,32 @@ public void testDisallowTrailingComma() throws Exception it.close(); } + + // [dataformats-text#204]: should also work for header line + + public void testWithTrailingHeaderComma() throws Exception + { + final String INPUT = "name,age,\n" + + "Roger,27,\n" + + "Chris,53,\n"; + final CsvSchema schema = CsvSchema.emptySchema().withHeader(); + + MappingIterator persons = MAPPER + .enable(CsvParser.Feature.ALLOW_TRAILING_COMMA) + .readerFor(Person.class) + .with(schema) + . readValues(INPUT); + assertTrue(persons.hasNextValue()); + Person p = persons.nextValue(); + assertNotNull(p); + assertEquals("Roger", p.name); + + assertTrue(persons.hasNextValue()); + p = persons.nextValue(); + assertNotNull(p); + assertEquals(53, p.age); + + assertFalse(persons.hasNextValue()); + persons.close(); + } } diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index a9de9442..01d28302 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -10,8 +10,10 @@ Modules: 2.10.5 (not yet released) -#146: Jackson can't handle underscores in numbers +#146: (yaml) Jackson can't handle underscores in numbers (reported by Sergey M; fix contributed by Conor W) +#204: (csv) `CsvParser.Feature.ALLOW_TRAILING_COMMA` doesn't work with header columns + (reported by Björn M) 2.10.4 (03-May-2020)