Unable to serialize top-level Java8 Stream
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).
Hmmh. Yes, so the work-around(s) used for Collections will not apply to Streams.
I suspect same problem would apply to Iterators / Iterables as well... although in most cases objects probably implement Collection.
It'd be nice to figure out something more general for iterable types (since they are not quite what CollectionLikeType covers unfortunately), but on short term (2.10, maybe even 2.9) I guess added check might be acceptable.
Realized that support probably requires upgrade of JDK baseline for XML module to be Java 8 -- something that is probably reasonable for 2.11, but can not be done in a patch for 2.10.
At this point Java 8 requirement is no longer blocker, fwtw.