序列化Java8流

序列化Java8流,java,json,jackson,Java,Json,Jackson,我想使用Jackson来序列化流的输出。Jackson不支持序列化java.util.stream.stream,但它能够序列化java.util.Iterator 为了说明这个问题,我想序列化这个平凡的接口: public interface SerializeMe { Iterator<Integer> getMyNumbers(); } 以下方法将演示这两个类的输出: public static void main(String[] args) throws Exce

我想使用Jackson来序列化流的输出。Jackson不支持序列化
java.util.stream.stream
,但它能够序列化
java.util.Iterator

为了说明这个问题,我想序列化这个平凡的接口:

public interface SerializeMe {
    Iterator<Integer> getMyNumbers();
}
以下方法将演示这两个类的输出:

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()));
}
此操作的输出为:

via list: {"myNumbers":[1,2,3]}
via stream: {"myNumbers":{}}
这表明流迭代器没有正确序列化

有趣的是,如果我添加
@JsonSerialize(as=Iterator.class)
,它确实可以工作:

@JsonSerialize(as=Iterator.class)
公共迭代器getMyNumbers(){
// ....
}

我不想为流可以创建的每个类型迭代器都编写自定义的
JsonSerializer
。我的替代方案是什么?

迭代器仅被识别为一个“附加”接口,也就是说,它仅在对象没有可构建的bean序列化程序时使用。不幸的是,spliterator适配器确实构建了一个伪bean序列化程序,因为该类有一个注释。。。这不是很好,甚至似乎与预期不符(这不是检查器使用afaik的注释)

当您指定
@JsonSerialize(as=Iterator.class)
时,您将强制解释为迭代器,迭代器序列化器工作正常

这是我之前编写的Jackson模块,它允许通过顺序序列化流的内容来序列化流(也可以是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);
        }
    }
}
公共类StreamModule扩展SimpleModule{
公共流模块(){
super(StreamModule.class.getSimpleName());
addSerializer(LongStream.class,新的LongStreamSerializer());
addSerializer(IntStream.class,新的IntStreamSerializer());
addSerializer(DoubleStream.class,新的DoubleStreamSerializer());
}
@凌驾
公共无效设置模块(设置上下文上下文){
addSerializers(新的StreamSerializers());
super.setupModule(上下文);
}
公共静态类StreamSerializers扩展了Serializers.Base{
@凌驾
公共JsonSerializer findSerializer(SerializationConfig配置、JavaType类型、BeanDescription beanDesc){
Class raw=type.getRawClass();
if(Stream.class.isAssignableFrom(原始)){
JavaType[]params=config.getTypeFactory().findTypeParameters(类型,Stream.class);
JavaType vt=(params==null | | params.length!=1)?TypeFactory.unknownType():params[0];
返回新的StreamSerializer(config.getTypeFactory().ConstructParameterizedType(Stream.class,Stream.class,vt),vt);
}
返回super.findSerializer(配置、类型、beanDesc);
}
}
静态类StreamSerializer扩展StdSerializer实现ContextualSerializer{
私有最终JavaType streamType;
私有最终JavaType elemType;
公共StreamSerializer(JavaType streamType、JavaType elemType){
超级(流线型);
this.streamType=streamType;
this.elemType=elemType;
}
@凌驾
公共JsonSerializer createContext(SerializerProvider提供程序,BeanProperty属性)引发JsonMappingException{
if(!elemType.hasRawClass(Object.class)&&(provider.isEnabled(MapperFeature.USE_STATIC_TYPING)| | elemType.isFinal()){
JsonSerializer elemSerializer=provider.findPrimaryPropertySerializer(elemType,property);
返回新的TypedStreamSerializer(streamType、elemSerializer);
}
归还这个;
}
@凌驾
public void serialize(Stream、JsonGenerator jgen、SerializerProvider提供程序)引发IOException,
JsonGenerationException{
jgen.writestarray();
试一试{
stream.forEachOrdered(元素->{
试一试{
provider.defaultSerializeValue(elem,jgen);
}捕获(IOE异常){
抛出新的WrappedIOException(e);
}
});
}捕获(包裹){
抛出(IOException)e.getCause();
}
jgen.writeEndArray();
}
}
静态类TypedStreamSerializer扩展了StdSerializer{
私人最终JsonSerializer elemSerializer;
@抑制警告(“未选中”)
公共类型流序列化程序(JavaType streamType、JsonSerializer和elemSerializer){
超级(流线型);
this.elemSerializer=(JsonSerializer)elemSerializer;
}
@凌驾
public void serialize(Stream、JsonGenerator jgen、SerializerProvider提供程序)引发IOException,
JsonGenerationException{
jgen.writestarray();
试一试{
stream.forEachOrdered(元素->{
试一试{
序列化(elem,jgen,provider);
}捕获(IOE异常){
抛出新的WrappedIOException(e);
}
});
}捕获(包裹){
抛出(IOException)e.getCause();
}
jgen.writeEndArray();
}
}
静态类IntStreamSerializer扩展了StdSerializer{
公共IntStreamSerializer(){
super(IntStream.class);
}
@凌驾
public void serialize(IntStream流、JsonGenerator jgen、SerializerProvider提供程序)引发IOException,
JsonGenerationException{
jgen.writestarray();
试一试{
stream.forEachOrdered(值->{
试一试{
jgen.writeNumber(值);
}捕获(IOE异常){
抛出新的W
@JsonSerialize(as=Iterator.class)
public Iterator<Integer> getMyNumbers() {
    // ....
}
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);
        }
    }
}