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

Commit 2233798

Browse files
authored
Merge pull request #127 from fivetran/always-quote-empty-strings
Option to force quoting of empty strings
2 parents fbaf351 + 6ee1b08 commit 2233798

File tree

3 files changed

+40
-7
lines changed

3 files changed

+40
-7
lines changed

src/main/java/com/fasterxml/jackson/dataformat/csv/CsvGenerator.java

+6
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ public enum Feature
6464
* @since 2.5
6565
*/
6666
ALWAYS_QUOTE_STRINGS(false),
67+
68+
/**
69+
* Feature that determines whether values written as empty Strings (from <code>java.lang.String</code>
70+
* valued POJO properties) should be forced to be quoted.
71+
*/
72+
ALWAYS_QUOTE_EMPTY_STRINGS(false),
6773
;
6874

6975
protected final boolean _defaultState;

src/main/java/com/fasterxml/jackson/dataformat/csv/impl/CsvEncoder.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ public class CsvEncoder
8888
* @since 2.5
8989
*/
9090
protected boolean _cfgAlwaysQuoteStrings;
91+
92+
protected boolean _cfgAlwaysQuoteEmptyStrings;
9193

9294
/*
9395
/**********************************************************
@@ -166,6 +168,7 @@ public CsvEncoder(IOContext ctxt, int csvFeatures, Writer out, CsvSchema schema)
166168
_cfgOptimalQuoting = CsvGenerator.Feature.STRICT_CHECK_FOR_QUOTING.enabledIn(csvFeatures);
167169
_cfgIncludeMissingTail = !CsvGenerator.Feature.OMIT_MISSING_TAIL_COLUMNS.enabledIn(_csvFeatures);
168170
_cfgAlwaysQuoteStrings = CsvGenerator.Feature.ALWAYS_QUOTE_STRINGS.enabledIn(csvFeatures);
171+
_cfgAlwaysQuoteEmptyStrings = CsvGenerator.Feature.ALWAYS_QUOTE_EMPTY_STRINGS.enabledIn(csvFeatures);
169172

170173
_outputBuffer = ctxt.allocConcatBuffer();
171174
_bufferRecyclable = true;
@@ -193,7 +196,8 @@ public CsvEncoder(CsvEncoder base, CsvSchema newSchema)
193196
_cfgOptimalQuoting = base._cfgOptimalQuoting;
194197
_cfgIncludeMissingTail = base._cfgIncludeMissingTail;
195198
_cfgAlwaysQuoteStrings = base._cfgAlwaysQuoteStrings;
196-
199+
_cfgAlwaysQuoteEmptyStrings = base._cfgAlwaysQuoteEmptyStrings;
200+
197201
_outputBuffer = base._outputBuffer;
198202
_bufferRecyclable = base._bufferRecyclable;
199203
_outputEnd = base._outputEnd;
@@ -232,6 +236,7 @@ public CsvEncoder overrideFormatFeatures(int feat) {
232236
_cfgOptimalQuoting = CsvGenerator.Feature.STRICT_CHECK_FOR_QUOTING.enabledIn(feat);
233237
_cfgIncludeMissingTail = !CsvGenerator.Feature.OMIT_MISSING_TAIL_COLUMNS.enabledIn(feat);
234238
_cfgAlwaysQuoteStrings = CsvGenerator.Feature.ALWAYS_QUOTE_STRINGS.enabledIn(feat);
239+
_cfgAlwaysQuoteEmptyStrings = CsvGenerator.Feature.ALWAYS_QUOTE_EMPTY_STRINGS.enabledIn(feat);
235240
}
236241
return this;
237242
}
@@ -870,6 +875,9 @@ protected boolean _mayNeedQuotes(String value, int length)
870875
if (_cfgEscapeCharacter > 0) {
871876
return _needsQuotingLoose(value, _cfgEscapeCharacter);
872877
}
878+
if (_cfgAlwaysQuoteEmptyStrings && length == 0) {
879+
return true;
880+
}
873881
return _needsQuotingLoose(value);
874882
}
875883

src/test/java/com/fasterxml/jackson/dataformat/csv/ser/TestGenerator.java

+25-6
Original file line numberDiff line numberDiff line change
@@ -190,20 +190,39 @@ public void testForcedQuoting60() throws Exception
190190
CsvMapper mapper = mapperForCsv();
191191
mapper.enable(CsvGenerator.Feature.ALWAYS_QUOTE_STRINGS);
192192
CsvSchema schema = CsvSchema.builder()
193-
.addColumn("id")
194-
.addColumn("amount")
195-
.build();
193+
.addColumn("id")
194+
.addColumn("amount")
195+
.build();
196196
String result = mapper.writer(schema)
197-
.writeValueAsString(new Entry("abc", 1.25));
197+
.writeValueAsString(new Entry("abc", 1.25));
198198
assertEquals("\"abc\",1.25\n", result);
199199

200200
// Also, as per [dataformat-csv#81], should be possible to change dynamically
201201
result = mapper.writer(schema)
202-
.without(CsvGenerator.Feature.ALWAYS_QUOTE_STRINGS)
203-
.writeValueAsString(new Entry("xyz", 2.5));
202+
.without(CsvGenerator.Feature.ALWAYS_QUOTE_STRINGS)
203+
.writeValueAsString(new Entry("xyz", 2.5));
204204
assertEquals("xyz,2.5\n", result);
205205
}
206206

207+
public void testForcedQuotingEmptyStrings() throws Exception
208+
{
209+
CsvMapper mapper = mapperForCsv();
210+
mapper.enable(CsvGenerator.Feature.ALWAYS_QUOTE_EMPTY_STRINGS);
211+
CsvSchema schema = CsvSchema.builder()
212+
.addColumn("id")
213+
.addColumn("amount")
214+
.build();
215+
String result = mapper.writer(schema)
216+
.writeValueAsString(new Entry("", 1.25));
217+
assertEquals("\"\",1.25\n", result);
218+
219+
// Also, as per [dataformat-csv#81], should be possible to change dynamically
220+
result = mapper.writer(schema)
221+
.without(CsvGenerator.Feature.ALWAYS_QUOTE_EMPTY_STRINGS)
222+
.writeValueAsString(new Entry("", 2.5));
223+
assertEquals(",2.5\n", result);
224+
}
225+
207226
// Must comment '#', at least if it starts the line
208227
public void testQuotingOfCommentChar() throws Exception
209228
{

0 commit comments

Comments
 (0)