Open
Description
A Stream
nested in another object is serialized using a value wrapper just as a collection or array, serializing a Stream
directly fails when more than one element is available as it tries to write a second root. If the Stream emits only a single element serialization works but without wrapping:
public class StreamTest {
private static final ObjectMapper OBJECT_MAPPER = new XmlMapper()
.registerModule(new Jdk8Module());
private static class StreamContainer {
@JsonProperty
private Stream<String> stream;
public StreamContainer(Stream<String> stream) { this.stream = stream; }
}
@Test
public void testTopLevelOneElement() throws JsonProcessingException {
assertNotEquals("<Head>a</Head>",
OBJECT_MAPPER.writeValueAsString(Stream.of("a")));
}
@Test
public void testTopLevelTwoElements() throws JsonProcessingException {
try {
assertEquals("<Head><item>a</item><item>b</item></Head>",
OBJECT_MAPPER.writeValueAsString(Stream.of("a", "b")));
} catch (JsonMappingException e) {
fail("Trying to output second root?", e);
}
}
@Test
public void testNestedOneElement() throws JsonProcessingException {
assertEquals("<StreamContainer><stream>a</stream></StreamContainer>",
OBJECT_MAPPER.writeValueAsString(new StreamContainer(Stream.of("a"))));
}
@Test
public void testNestedTwoElements() throws JsonProcessingException {
assertEquals("<StreamContainer><stream>a</stream><stream>b</stream></StreamContainer>",
OBJECT_MAPPER.writeValueAsString(new StreamContainer(Stream.of("a", "b"))));
}
}
The root element name is Head
for Stream serialization as it's determined from the actual class name ReferencePipeline$Head
.
The cause lies in TypeUtil.isIndexedType(Class<?>)
which just checks for Arrays and Collections and only if this returns true, a field name is written (and _nextName set).
It works for the nested Stream as _nextName
is set due to the Stream being written as a field (multiple times).