我想用Jackson来序列化流的输出.杰克逊没有对序列化的内在支持java.util.stream.Stream,但它能够序列化java.util.Iterator.
为了说明这个问题,我想序列化这个简单的界面:
public interface SerializeMe {
Iterator<Integer> getMyNumbers();
}
Run Code Online (Sandbox Code Playgroud)
我将比较序列化List.iterator()与输出的输出Stream.iterator():
public class SerializeViaList implements SerializeMe {
@Override
public Iterator<Integer> getMyNumbers() {
return Arrays.asList(1, 2, 3).iterator();
}
}
public class SerializeViaStream implements SerializeMe {
@Override
public Iterator<Integer> getMyNumbers() {
return Arrays.asList(1, 2, 3).stream().iterator();
}
}
Run Code Online (Sandbox Code Playgroud)
以下方法将演示这两个类的输出:
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
System.out.println("via list: " + mapper.writeValueAsString(new SerializeViaList()));
System.out.println("via stream: " + mapper.writeValueAsString(new SerializeViaStream()));
}
Run Code Online (Sandbox Code Playgroud)
这个输出是:
via list: {"myNumbers":[1,2,3]}
via stream: {"myNumbers":{}}
Run Code Online (Sandbox Code Playgroud)
这表明流迭代器未正确序列化.
有趣的是,如果我添加它确实有效@JsonSerialize(as=Iterator.class):
@JsonSerialize(as=Iterator.class)
public Iterator<Integer> getMyNumbers() {
// ....
}
Run Code Online (Sandbox Code Playgroud)
我不想为JsonSerializer流可以创建的每个类型迭代器编写自定义.我有什么选择?
Iterator只被识别为"附加"接口,即只有在没有bean序列化程序可以为对象构建时才使用它.不幸的是,spliterator适配器确实得到了一个虚拟bean序列化器,因为该类有一个注释...这不是很好,甚至看起来不是很符合预期(这不是检查员使用的注释)据我所知)
当您指定@JsonSerialize(as=Iterator.class)强制解释为迭代器时,IteratorSerializer工作正常.
这是我之前编写的Jackson模块,它允许通过顺序序列化其内容来序列化Stream(也是LongStream,IntStream或DoubleStream):
public class StreamModule extends SimpleModule {
public StreamModule() {
super(StreamModule.class.getSimpleName());
addSerializer(LongStream.class, new LongStreamSerializer());
addSerializer(IntStream.class, new IntStreamSerializer());
addSerializer(DoubleStream.class, new DoubleStreamSerializer());
}
@Override
public void setupModule(SetupContext context) {
context.addSerializers(new StreamSerializers());
super.setupModule(context);
}
public static class StreamSerializers extends Serializers.Base {
@Override
public JsonSerializer<?> findSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc) {
Class<?> raw = type.getRawClass();
if (Stream.class.isAssignableFrom(raw)) {
JavaType[] params = config.getTypeFactory().findTypeParameters(type, Stream.class);
JavaType vt = (params == null || params.length != 1) ? TypeFactory.unknownType() : params[0];
return new StreamSerializer<Object>(config.getTypeFactory().constructParametrizedType(Stream.class, Stream.class, vt), vt);
}
return super.findSerializer(config, type, beanDesc);
}
}
static class StreamSerializer<T> extends StdSerializer<Stream<T>> implements ContextualSerializer {
private final JavaType streamType;
private final JavaType elemType;
public StreamSerializer(JavaType streamType, JavaType elemType) {
super(streamType);
this.streamType = streamType;
this.elemType = elemType;
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException {
if (!elemType.hasRawClass(Object.class) && (provider.isEnabled(MapperFeature.USE_STATIC_TYPING) || elemType.isFinal())) {
JsonSerializer<Object> elemSerializer = provider.findPrimaryPropertySerializer(elemType, property);
return new TypedStreamSerializer<T>(streamType, elemSerializer);
}
return this;
}
@Override
public void serialize(Stream<T> stream, JsonGenerator jgen, SerializerProvider provider) throws IOException,
JsonGenerationException {
jgen.writeStartArray();
try {
stream.forEachOrdered(elem -> {
try {
provider.defaultSerializeValue(elem, jgen);
} catch (IOException e) {
throw new WrappedIOException(e);
}
});
} catch (WrappedIOException e) {
throw (IOException) e.getCause();
}
jgen.writeEndArray();
}
}
static class TypedStreamSerializer<T> extends StdSerializer<Stream<T>> {
private final JsonSerializer<T> elemSerializer;
@SuppressWarnings("unchecked")
public TypedStreamSerializer(JavaType streamType, JsonSerializer<?> elemSerializer) {
super(streamType);
this.elemSerializer = (JsonSerializer<T>) elemSerializer;
}
@Override
public void serialize(Stream<T> stream, JsonGenerator jgen, SerializerProvider provider) throws IOException,
JsonGenerationException {
jgen.writeStartArray();
try {
stream.forEachOrdered(elem -> {
try {
elemSerializer.serialize(elem, jgen, provider);
} catch (IOException e) {
throw new WrappedIOException(e);
}
});
} catch (WrappedIOException e) {
throw (IOException) e.getCause();
}
jgen.writeEndArray();
}
}
static class IntStreamSerializer extends StdSerializer<IntStream> {
public IntStreamSerializer() {
super(IntStream.class);
}
@Override
public void serialize(IntStream stream, JsonGenerator jgen, SerializerProvider provider) throws IOException,
JsonGenerationException {
jgen.writeStartArray();
try {
stream.forEachOrdered(value -> {
try {
jgen.writeNumber(value);
} catch (IOException e) {
throw new WrappedIOException(e);
}
});
} catch (WrappedIOException e) {
throw (IOException) e.getCause();
}
jgen.writeEndArray();
}
}
static class LongStreamSerializer extends StdSerializer<LongStream> {
public LongStreamSerializer() {
super(LongStream.class);
}
@Override
public void serialize(LongStream stream, JsonGenerator jgen, SerializerProvider provider) throws IOException,
JsonGenerationException {
jgen.writeStartArray();
try {
stream.forEachOrdered(value -> {
try {
jgen.writeNumber(value);
} catch (IOException e) {
throw new WrappedIOException(e);
}
});
} catch (WrappedIOException e) {
throw (IOException) e.getCause();
}
jgen.writeEndArray();
}
}
static class DoubleStreamSerializer extends StdSerializer<DoubleStream> {
public DoubleStreamSerializer() {
super(DoubleStream.class);
}
@Override
public void serialize(DoubleStream stream, JsonGenerator jgen, SerializerProvider provider) throws IOException,
JsonGenerationException {
jgen.writeStartArray();
try {
stream.forEachOrdered(value -> {
try {
jgen.writeNumber(value);
} catch (IOException e) {
throw new WrappedIOException(e);
}
});
} catch (WrappedIOException e) {
throw (IOException) e.getCause();
}
jgen.writeEndArray();
}
}
public static final class WrappedIOException extends RuntimeException {
private WrappedIOException(IOException e) {
super(e);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1916 次 |
| 最近记录: |