Skip to content

Commit 0c6a4fb

Browse files
authored
Fix handling of null values in string Arrays and Collections (#585)
1 parent 99596c6 commit 0c6a4fb

File tree

2 files changed

+172
-3
lines changed

2 files changed

+172
-3
lines changed

src/main/java/com/fasterxml/jackson/dataformat/xml/deser/FromXmlParser.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -932,12 +932,11 @@ public String nextTextValue() throws IOException
932932
switch (token) {
933933
case XmlTokenStream.XML_END_ELEMENT:
934934
if (_mayBeLeaf) {
935-
// NOTE: this is different from nextToken() -- produce "", NOT null
936935
_mayBeLeaf = false;
937-
_currToken = JsonToken.VALUE_STRING;
936+
_currToken = JsonToken.VALUE_NULL;
938937
// 13-May-2020, tatu: [dataformat-xml#397]: advance `index`
939938
_parsingContext.valueStarted();
940-
return (_currText = "");
939+
return (_currText = null);
941940
}
942941
_currToken = _parsingContext.inArray() ? JsonToken.END_ARRAY : JsonToken.END_OBJECT;
943942
_parsingContext = _parsingContext.getParent();
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
package com.fasterxml.jackson.dataformat.xml.lists;
2+
3+
import java.util.HashMap;
4+
import java.util.List;
5+
import java.util.Map;
6+
7+
import org.junit.Test;
8+
9+
import com.fasterxml.jackson.core.type.TypeReference;
10+
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
11+
12+
import static com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser.Feature.PROCESS_XSI_NIL;
13+
import static com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator.Feature.WRITE_NULLS_AS_XSI_NIL;
14+
import static java.util.Arrays.asList;
15+
import static org.junit.Assert.assertEquals;
16+
import static org.junit.Assert.assertNotNull;
17+
import static org.junit.Assert.assertNull;
18+
19+
// [dataformat-xml#584]
20+
public class StringListRoundtripTest {
21+
private final static XmlMapper MAPPER = new XmlMapper();
22+
23+
@Test
24+
public void testStringArray() throws Exception
25+
{
26+
// default mode, should get back empty string
27+
MAPPER.disable(WRITE_NULLS_AS_XSI_NIL);
28+
MAPPER.enable(PROCESS_XSI_NIL);
29+
stringArrayRoundtrip(false);
30+
31+
// xsi null enabled, should get back null
32+
MAPPER.enable(WRITE_NULLS_AS_XSI_NIL);
33+
MAPPER.enable(PROCESS_XSI_NIL);
34+
stringArrayRoundtrip(true);
35+
36+
// xsi null write enabled but processing disabled, should get back empty string
37+
MAPPER.enable(WRITE_NULLS_AS_XSI_NIL);
38+
MAPPER.disable(PROCESS_XSI_NIL);
39+
stringArrayRoundtrip(false);
40+
}
41+
42+
private void stringArrayRoundtrip(boolean shouldBeNull) throws Exception
43+
{
44+
String[] array = new String[] {"", "test", null, "test2"};
45+
46+
// serialize to string
47+
String xml = MAPPER.writeValueAsString(array);
48+
assertNotNull(xml);
49+
50+
// then bring it back
51+
String[] result = MAPPER.readValue(xml, String[].class);
52+
assertEquals(4, result.length);
53+
assertEquals("", result[0]);
54+
assertEquals("test", result[1]);
55+
if (shouldBeNull)
56+
{
57+
assertNull(result[2]);
58+
} else
59+
{
60+
assertEquals("", result[2]);
61+
}
62+
assertEquals("test2", result[3]);
63+
}
64+
65+
@Test
66+
public void testStringList() throws Exception
67+
{
68+
// default mode, should get back empty string
69+
MAPPER.disable(WRITE_NULLS_AS_XSI_NIL);
70+
MAPPER.enable(PROCESS_XSI_NIL);
71+
stringListRoundtrip(false);
72+
73+
// xsi null enabled, should get back null
74+
MAPPER.enable(WRITE_NULLS_AS_XSI_NIL);
75+
MAPPER.enable(PROCESS_XSI_NIL);
76+
stringListRoundtrip(true);
77+
78+
// xsi null write enabled but processing disabled, should get back empty string
79+
MAPPER.enable(WRITE_NULLS_AS_XSI_NIL);
80+
MAPPER.disable(PROCESS_XSI_NIL);
81+
stringListRoundtrip(false);
82+
}
83+
84+
private void stringListRoundtrip(boolean shouldBeNull) throws Exception
85+
{
86+
List<String> list = asList("", "test", null, "test2");
87+
88+
// serialize to string
89+
String xml = MAPPER.writeValueAsString(list);
90+
assertNotNull(xml);
91+
92+
// then bring it back
93+
List<String> result = MAPPER.readValue(xml, new TypeReference<List<String>>() {});
94+
assertEquals(4, result.size());
95+
assertEquals("", result.get(0));
96+
assertEquals("test", result.get(1));
97+
if (shouldBeNull)
98+
{
99+
assertNull(result.get(2));
100+
} else
101+
{
102+
assertEquals("", result.get(2));
103+
}
104+
assertEquals("test2", result.get(3));
105+
}
106+
107+
@Test
108+
public void testStringMap() throws Exception
109+
{
110+
// default mode, should get back empty string
111+
MAPPER.disable(WRITE_NULLS_AS_XSI_NIL);
112+
MAPPER.enable(PROCESS_XSI_NIL);
113+
stringMapRoundtrip(false);
114+
115+
// xsi null enabled, should get back null
116+
MAPPER.enable(WRITE_NULLS_AS_XSI_NIL);
117+
MAPPER.enable(PROCESS_XSI_NIL);
118+
stringMapRoundtrip(true);
119+
120+
// xsi null write enabled but processing disabled, should get back empty string
121+
MAPPER.enable(WRITE_NULLS_AS_XSI_NIL);
122+
MAPPER.disable(PROCESS_XSI_NIL);
123+
stringMapRoundtrip(false);
124+
}
125+
126+
private void stringMapRoundtrip(boolean shouldBeNull) throws Exception
127+
{
128+
Map<String, String> map = new HashMap<String, String>() {{
129+
put("a", "");
130+
put("b", "test");
131+
put("c", null);
132+
put("d", "test2");
133+
}};
134+
MapPojo mapPojo = new MapPojo();
135+
mapPojo.setMap( map );
136+
137+
// serialize to string
138+
String xml = MAPPER.writeValueAsString(mapPojo);
139+
assertNotNull(xml);
140+
141+
// then bring it back
142+
MapPojo result = MAPPER.readValue(xml, MapPojo.class);
143+
assertEquals(4, result.map.size());
144+
assertEquals("", result.map.get("a"));
145+
assertEquals("test", result.map.get("b"));
146+
if (shouldBeNull)
147+
{
148+
assertNull(result.map.get("c"));
149+
} else
150+
{
151+
assertEquals("", result.map.get("c"));
152+
}
153+
assertEquals("test2", result.map.get("d"));
154+
}
155+
156+
private static class MapPojo {
157+
private Map<String, String> map;
158+
159+
public MapPojo() {
160+
}
161+
162+
public Map<String, String> getMap() {
163+
return map;
164+
}
165+
166+
public void setMap(Map<String, String> map) {
167+
this.map = map;
168+
}
169+
}
170+
}

0 commit comments

Comments
 (0)