gpt4 book ai didi

java - 序列化 Java 8 流

转载 作者:行者123 更新时间:2023-11-30 06:11:04 25 4
gpt4 key购买 nike

我想使用 Jackson 序列化流的输出。 Jackson 没有对序列化 java.util.stream.Stream 的内在支持,但它能够序列化 java.util.Iterator

为了说明问题,我想序列化这个微不足道的接口(interface):

public interface SerializeMe {
Iterator<Integer> getMyNumbers();
}

我将比较序列化 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();
}
}

以下方法将演示这两个类的输出:

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)
public Iterator<Integer> getMyNumbers() {
// ....
}

我不想为流可以创建的每个类型迭代器编写自定义 JsonSerializer。我有哪些选择?

最佳答案

Iterator 仅被识别为“附加”接口(interface),即仅在没有可用于对象的 bean 序列化器时才使用它。不幸的是,spliterator 适配器确实构建了一个虚拟 bean 序列化程序,因为该类有一个注解……这不是很好,甚至似乎不是预期的(这不是检查员使用的注解)据我所知)

当您指定 @JsonSerialize(as=Iterator.class) 时,您强制解释为 Iterator,并且 IteratorSerializer 工作正常。

这是我之前编写的一个 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);
}
}
}

关于java - 序列化 Java 8 流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34748282/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com