From 1532adb144af9ea38917db5bc094423eb8270b1f Mon Sep 17 00:00:00 2001 From: Tyler Carpenter-Rivers Date: Mon, 30 Sep 2019 17:30:53 -0700 Subject: [PATCH] (csv) Support coercion of empty strings to null objects https://github.com/FasterXML/jackson-dataformats-text/issues/7 --- .../jackson/dataformat/csv/CsvParser.java | 10 +++ .../csv/deser/EmptyStringAsNullTest.java | 65 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 csv/src/test/java/com/fasterxml/jackson/dataformat/csv/deser/EmptyStringAsNullTest.java 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 38f11e50..50baa8b7 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 @@ -123,6 +123,13 @@ public enum Feature * Feature is disabled by default. */ INSERT_NULLS_FOR_MISSING_COLUMNS(false), + + /** + * Feature that enables coercing an empty {@link String} to `null` + * + * Feature is disabled by default + */ + EMPTY_STRING_AS_NULL(false) ; final boolean _defaultState; @@ -1056,6 +1063,9 @@ public String getText() throws IOException { if (_currToken == JsonToken.FIELD_NAME) { return _currentName; } + if (_currentValue.equals("")) { + return isEnabled(CsvParser.Feature.EMPTY_STRING_AS_NULL) ? null : _currentValue; + } return _currentValue; } diff --git a/csv/src/test/java/com/fasterxml/jackson/dataformat/csv/deser/EmptyStringAsNullTest.java b/csv/src/test/java/com/fasterxml/jackson/dataformat/csv/deser/EmptyStringAsNullTest.java new file mode 100644 index 00000000..9f8c35ad --- /dev/null +++ b/csv/src/test/java/com/fasterxml/jackson/dataformat/csv/deser/EmptyStringAsNullTest.java @@ -0,0 +1,65 @@ +package com.fasterxml.jackson.dataformat.csv.deser; + +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.dataformat.csv.CsvMapper; +import com.fasterxml.jackson.dataformat.csv.CsvParser; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.*; + +/** + * Test for {@link CsvParser.Feature#EMPTY_STRING_AS_NULL} + */ +public class EmptyStringAsNullTest { + + + @JsonPropertyOrder({"firstName", "middleName", "lastName"}) + static class TestUser { + public String firstName, middleName, lastName; + } + + @Test + public void givenFeatureDisabledByDefault_whenColumnIsEmptyString_thenParseAsEmptyString() throws IOException { + // setup test data + TestUser expectedTestUser = new TestUser(); + expectedTestUser.firstName = "Grace"; + expectedTestUser.middleName = ""; + expectedTestUser.lastName = "Hopper"; + CsvMapper csvMapper = CsvMapper.builder().build(); + ObjectReader objectReader = csvMapper.readerFor(TestUser.class).with(csvMapper.schemaFor(TestUser.class)); + String csv = "Grace,,Hopper"; + + // execute + TestUser actualTestUser = objectReader.readValue(csv); + + // test + assertNotNull(actualTestUser); + assertEquals(expectedTestUser.firstName, actualTestUser.firstName); + assertEquals(expectedTestUser.middleName, actualTestUser.middleName); + assertEquals(expectedTestUser.lastName, actualTestUser.lastName); + } + + @Test + public void givenFeatureEnabled_whenColumnIsEmptyString_thenParseAsNull() throws IOException { + // setup test data + TestUser expectedTestUser = new TestUser(); + expectedTestUser.firstName = "Grace"; + expectedTestUser.lastName = "Hopper"; + CsvMapper csvMapper = CsvMapper.builder().enable(CsvParser.Feature.EMPTY_STRING_AS_NULL).build(); + ObjectReader objectReader = csvMapper.readerFor(TestUser.class).with(csvMapper.schemaFor(TestUser.class)); + String csv = "Grace,,Hopper"; + + // execute + TestUser actualTestUser = objectReader.readValue(csv); + + // test + assertNotNull(actualTestUser); + assertEquals(expectedTestUser.firstName, actualTestUser.firstName); + assertNull("The column that contains an empty String should be deserialized as null ", actualTestUser.middleName); + assertEquals(expectedTestUser.lastName, actualTestUser.lastName); + } +}