Skip to content
This repository has been archived by the owner on Jan 22, 2019. It is now read-only.

Commit

Permalink
One more fix wrt #72, to distinguish between empty String, null, when…
Browse files Browse the repository at this point in the history
… reading; only former will cause coercion of empty String into `null`, at streaming parser level (higher-level mapping may still occur).
  • Loading branch information
cowtowncoder committed Jun 29, 2015
1 parent b249d53 commit 98d2f1a
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ public void writeNull() throws IOException
_verifyValueWrite("write null value");
if (!_skipValue) {
if (_arraySeparator >= 0) {
_addToArray(_schema.getNullValue());
_addToArray(_schema.getNullValueOrEmpty());
} else if (_writeContext.inRoot()) { // as per [#69]
// or, to write 'empty Object' (for common case), would
// write single null, then finish row, like so:
Expand Down
42 changes: 33 additions & 9 deletions src/main/java/com/fasterxml/jackson/dataformat/csv/CsvSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ public class CsvSchema

protected final static int DEFAULT_ENCODING_FEATURES = 0;

protected final static char[] NO_CHARS = new char[0];

/*
/**********************************************************************
/* Constants, default settings
Expand All @@ -100,13 +102,20 @@ public class CsvSchema
* semicolon.
*/
public final static char DEFAULT_ARRAY_ELEMENT_SEPARATOR = ';';

public final static char DEFAULT_QUOTE_CHAR = '"';

/**
* By default, nulls are written as empty Strings ("")
* By default, nulls are written as empty Strings (""); and no coercion
* is performed from any String (higher level databind may, however,
* coerce Strings into Java nulls).
* To use automatic coercion on reading, null value must be set explicitly
* to empty String ("").
*<p>
* NOTE: before 2.6, this value default to empty <code>char[]</code>; changed
* to Java null in 2.6.
*/
public final static char[] DEFAULT_NULL_VALUE = new char[0];
public final static char[] DEFAULT_NULL_VALUE = null;

/**
* By default, no escape character is used -- this is denoted by
Expand Down Expand Up @@ -549,7 +558,7 @@ public Builder setNullValue(String nvl) {
}

public Builder setNullValue(char[] nvl) {
_nullValue = (nvl == null) ? DEFAULT_NULL_VALUE : nvl;
_nullValue = nvl;
return this;
}

Expand Down Expand Up @@ -888,7 +897,7 @@ public CsvSchema withNullValue(String nvl) {
return new CsvSchema(_columns, _features,
_columnSeparator, _quoteChar, _escapeChar, _lineSeparator,
_arrayElementSeparator,
(nvl == null) ? DEFAULT_NULL_VALUE : nvl.toCharArray(),
(nvl == null) ? null : nvl.toCharArray(),
_columnsByName);
}

Expand Down Expand Up @@ -982,21 +991,36 @@ public String getSchemaType() {
public char[] getLineSeparator() { return _lineSeparator; }

/**
* @return Null value defined, as char array, if one is defined to be recognized; Java null
* if not.
*
* @since 2.5
*/
public char[] getNullValue() { return _nullValue; }

/**
* Same as {@link #getNullValue()} except that undefined null value (one that remains as <code>null</code>,
* or explicitly set as such) will be returned as empty <code>char[]</code>
*
* @since 2.6
*/
public char[] getNullValueOrEmpty() {
if (_nullValue == null) {
return NO_CHARS;
}
return _nullValue;
}

/**
* @since 2.6
*/
public String getNullValueString() {
String str = _nullValueAsString;
if (str == null) {
if (_nullValue == null || _nullValue.length == 0) {
str = "";
} else {
str = new String(_nullValue);
if (_nullValue == null) {
return null;
}
str = (_nullValue.length == 0) ? "" : new String(_nullValue);
_nullValueAsString = str;
}
return str;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public CsvEncoder(IOContext ctxt, int csvFeatures, Writer out, CsvSchema schema)
_cfgQuoteCharacter = schema.getQuoteChar();
_cfgLineSeparator = schema.getLineSeparator();
_cfgLineSeparatorLength = (_cfgLineSeparator == null) ? 0 : _cfgLineSeparator.length;
_cfgNullValue = schema.getNullValue();
_cfgNullValue = schema.getNullValueOrEmpty();

_columnCount = schema.size();

Expand All @@ -198,7 +198,7 @@ public CsvEncoder(CsvEncoder base, CsvSchema newSchema)
_cfgQuoteCharacter = newSchema.getQuoteChar();
_cfgLineSeparator = newSchema.getLineSeparator();
_cfgLineSeparatorLength = _cfgLineSeparator.length;
_cfgNullValue = newSchema.getNullValue();
_cfgNullValue = newSchema.getNullValueOrEmpty();
_cfgMinSafeChar = _calcSafeChar();
_columnCount = newSchema.size();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,19 @@ public void testReadNullValueFromEmptyString() throws Exception
String csv = MAPPER.writer(schemaWithDefault).writeValueAsString(new IdDesc("id", null));
assertEquals("id,\n", csv);

// but read back
// but read back. Note: no null coercion unless explicitly defined

ObjectReader r = MAPPER.readerFor(IdDesc.class).with(schemaWithDefault);

IdDesc result = r.readValue(csv);
assertNotNull(result);
assertEquals("id", result.id);
assertNull(result.desc);
assertEquals("", result.desc);

// also try the other combination
result = r.readValue(",Whatevs\n");
assertNotNull(result);
assertNull(result.id);
assertEquals("", result.id);
assertEquals("Whatevs", result.desc);

// And then with explicit Empty String
Expand All @@ -80,7 +80,7 @@ public void testReadNullValueFromEmptyString() throws Exception
assertEquals("id", result.id);
assertNull(result.desc);

// and finally with explicit `null`
// and finally with explicit `null`, which once again disables coercion
CsvSchema schemaWithExplicitNull = CsvSchema.builder()
.setNullValue((String) null)
.addColumn("id")
Expand All @@ -93,6 +93,6 @@ public void testReadNullValueFromEmptyString() throws Exception
result = r.readValue(csv);
assertNotNull(result);
assertEquals("id", result.id);
assertNull(result.desc);
assertEquals("", result.desc);
}
}

0 comments on commit 98d2f1a

Please sign in to comment.