Skip to content

Commit 873598d

Browse files
committed
Merge branch '2.x' into 3.0
2 parents e0dc01e + e5beb4b commit 873598d

File tree

4 files changed

+41
-32
lines changed

4 files changed

+41
-32
lines changed

csv/src/main/java/tools/jackson/dataformat/csv/CsvGenerator.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,15 @@ public class CsvGenerator extends GeneratorBase
8181
*/
8282
protected boolean _skipValue;
8383

84+
/**
85+
* Flag set when a row has just been finished, used to distinguish between
86+
* null values within a row vs null rows.
87+
* Only relevant for Array-wrapped rows.
88+
*
89+
* @since 2.21
90+
*/
91+
protected boolean _justFinishedRow = false;
92+
8493
/**
8594
* Separator to use during writing of (simple) array value, to be encoded as a
8695
* single column value, if any.
@@ -354,6 +363,7 @@ protected void _closeInput() throws IOException
354363
public JsonGenerator writeStartArray() throws JacksonException
355364
{
356365
_verifyValueWrite("start an array");
366+
_justFinishedRow = false; // Clear flag when starting new array
357367
// Ok to create root-level array to contain Objects/Arrays, but
358368
// can not nest arrays in objects
359369
if (_streamWriteContext.inObject()) {
@@ -437,6 +447,8 @@ public JsonGenerator writeEndArray() throws JacksonException
437447
public JsonGenerator writeStartObject() throws JacksonException
438448
{
439449
_verifyValueWrite("start an object");
450+
_justFinishedRow = false;
451+
440452
// No nesting for objects; can write Objects inside logical root-level arrays.
441453
// 14-Dec-2015, tatu: ... except, should be fine if we are ignoring the property
442454
if (_streamWriteContext.inObject() ||
@@ -703,7 +715,12 @@ public JsonGenerator writeNull() throws JacksonException
703715
// just skip; can change, if so desired, to expose "root null" as empty rows, possibly
704716
// based on either schema property, or CsvGenerator.Feature.
705717
// Note: if nulls are to be written that way, would need to call `finishRow()` right after `writeNull()`
706-
if (!_streamWriteContext.getParent().inRoot()) {
718+
// [dataformats-text#10]: When we have a schema and we haven't just finished a row,
719+
// it means we're inside an array-as-row (like Object[]), so null is a column value
720+
boolean writeNullValue = !_streamWriteContext.getParent().inRoot()
721+
|| (_schema.size() > 0 && !_justFinishedRow);
722+
723+
if (writeNullValue) {
707724
// 26-Aug-2024, tatu: [dataformats-text#495] Decorations?
708725
if (_nextColumnDecorator != null) {
709726
String nvl = _nextColumnDecorator.decorateNull(this);
@@ -961,6 +978,7 @@ protected void finishRow() throws JacksonException
961978
{
962979
_writer.endRow();
963980
_nextColumnByName = -1;
981+
_justFinishedRow = true;
964982
}
965983

966984
protected void _handleFirstLine() throws JacksonException
Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tools.jackson.dataformat.csv.tofix;
1+
package tools.jackson.dataformat.csv.ser;
22

33
import java.io.StringWriter;
44

@@ -7,16 +7,12 @@
77
import tools.jackson.databind.ObjectWriter;
88
import tools.jackson.databind.SequenceWriter;
99
import tools.jackson.dataformat.csv.*;
10-
import tools.jackson.dataformat.csv.testutil.failure.JacksonTestFailureExpected;
1110

1211
import static org.junit.jupiter.api.Assertions.assertEquals;
1312

14-
public class MissingNullsOnObjectArrayWrite10Test extends ModuleTestBase
13+
public class ObjectArrayNullWrite10Test extends ModuleTestBase
1514
{
16-
private final CsvMapper MAPPER = mapperForCsv();
17-
1815
// for [dataformats-text#10]
19-
@JacksonTestFailureExpected
2016
@Test
2117
public void testNullsOnObjectArrayWrites2Col() throws Exception
2218
{
@@ -25,13 +21,14 @@ public void testNullsOnObjectArrayWrites2Col() throws Exception
2521
.addColumn("b", CsvSchema.ColumnType.NUMBER)
2622
.setUseHeader(true)
2723
.build();
28-
ObjectWriter writer = MAPPER.writer(schema);
24+
ObjectWriter writer = mapperForCsv().writer(schema);
2925
StringWriter out = new StringWriter();
30-
SequenceWriter sequence = writer.writeValues(out);
3126

32-
sequence.write(new Object[]{ null, 2 });
33-
sequence.write(new Object[]{ null, null });
34-
sequence.write(new Object[]{ 1, null });
27+
try (SequenceWriter sequence = writer.writeValues(out)) {
28+
sequence.write(new Object[]{ null, 2 });
29+
sequence.write(new Object[]{ null, null });
30+
sequence.write(new Object[]{ 1, null });
31+
}
3532

3633
final String csv = out.toString().trim();
3734

Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package tools.jackson.dataformat.csv.tofix;
1+
package tools.jackson.dataformat.csv.ser;
22

33
import java.io.StringWriter;
44

@@ -7,41 +7,34 @@
77
import tools.jackson.databind.ObjectWriter;
88
import tools.jackson.databind.SequenceWriter;
99
import tools.jackson.dataformat.csv.*;
10-
import tools.jackson.dataformat.csv.testutil.failure.JacksonTestFailureExpected;
1110

1211
import static org.junit.jupiter.api.Assertions.assertEquals;
1312

14-
public class NullWriting116Test extends ModuleTestBase
13+
public class ObjectArrayNullWrite116Test extends ModuleTestBase
1514
{
16-
private final CsvMapper csv = mapperForCsv();
17-
18-
// [dataformat#116]
19-
@JacksonTestFailureExpected
15+
// for [dataformats-text#116]
2016
@Test
21-
public void testWithObjectArray() throws Exception
17+
public void testWithObjectArray() throws Exception
2218
{
2319
CsvSchema schema = CsvSchema.builder()
2420
.addColumn("a", CsvSchema.ColumnType.NUMBER)
2521
.addColumn("b", CsvSchema.ColumnType.NUMBER)
2622
.setUseHeader(true)
2723
.build();
28-
ObjectWriter writer = csv.writer(schema);
24+
ObjectWriter writer = mapperForCsv().writer(schema);
2925
StringWriter out = new StringWriter();
30-
SequenceWriter sequence = writer.writeValues(out);
31-
32-
sequence.write(new Object[]{ 1, 2 });
33-
// sequence.write(new Object[]{ null, 2 });
34-
sequence.write(new Object[]{ null, null });
35-
sequence.write(new Object[]{ 1, null });
3626

37-
sequence.close();
27+
try (SequenceWriter sequence = writer.writeValues(out)) {
28+
sequence.write(new Object[]{ 1, 2 });
29+
sequence.write(new Object[]{ null, 2 });
30+
sequence.write(new Object[]{ null, null });
31+
sequence.write(new Object[]{ 1, null });
32+
}
3833

39-
//System.err.println("CSV:\n"+out);
4034
assertEquals("a,b\n" +
4135
"1,2\n" +
42-
// ",2\n" +
36+
",2\n" +
4337
",\n" +
4438
"1,\n", out.toString());
4539
}
46-
4740
}

release-notes/VERSION-2.x

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ Active Maintainers:
1616

1717
2.21.0 (not yet released)
1818

19-
No changes since 2.20
19+
#10: Missing `null` writes when writing `Object[]` values
20+
(fix by @cowtowncoder, w/ Claude code)
2021

2122
2.20.1 (30-Oct-2025)
2223

0 commit comments

Comments
 (0)