如何使用Jackson序列化/反序列化java.util.stream.Stream?

时间:2015-03-17 15:38:36

标签: jackson java-8

假设我有以下对象

public class DataObjectA {
    private Stream<DataObjectB> dataObjectBStream;
}

如何使用Jackson序列化它们?

4 个答案:

答案 0 :(得分:4)

正如其他人所指出的,你只能在一个流上迭代一次。如果这对您有用,您可以使用它来序列化:

new ObjectMapper().writerFor(Iterator.class).writeValueAsString(dataObjectBStream.iterator())

如果您使用的是2.5之前的Jackson版本,请使用writerWithType()代替writerFor()

答案 1 :(得分:2)

有关向Jackson提供java.util.Stream支持的未解决问题,请参阅https://github.com/FasterXML/jackson-modules-java8/issues/3。这里包含了初步版本的代码。 (编辑:现在已合并并在2.9.0中支持)。

如果流是您(de)序列化的顶级对象,例如从JAX-RS资源返回java.util.stream.Stream<T>或读取Stream,则流支持感觉就像它会自然/安全地工作一样来自JAX-RS客户端。

作为(de)序列化对象的成员变量,Stream就像你的例子中一样,比较棘手,因为它是可变的和单一用途的:

  

private Stream<DataObjectB> dataObjectBStream;

假设它受到支持,所有关于存储对流的引用的警告都将适用。您不可能多次序列化对象,并且一旦您对包装对象进行反序列化,可能它的流成员将通过JAX-RS客户端和HTTP连接保留实时连接,这可能会创建惊喜。

答案 2 :(得分:1)

你没有。

Stream是一次性使用的操作链,从不打算持久化。即使将它存储到像你的问题中的实例字段中也是误解其目的的指标。一旦在流上应用了终端操作,它就没用了,也无法克隆流。这样就没有必要记住字段中不可用的流。

由于Stream提供的唯一操作是将更多操作链接到管道并最终对其进行评估,因此无法查询其状态,从而允许创建关于其行为的等效流。因此,没有持久性框架可以存储它。框架唯一能做的就是遍历流操作的结果元素并存储它们,但这意味着有效地存储一种对象集合而不是Stream。除此之外,Stream的一次性使用也意味着遍历流以存储元素的存储框架具有使流不能同时使用的副作用。

如果您想存储元素,请使用普通的Collection

另一方面,如果你真的想存储行为,你最终将存储一个实际类实现行为的对象实例。这仍然适用于Stream,因为您可以存储具有生成所需流的工厂方法的类的实例。当然,您并没有真正存储行为,而是对其进行符号引用,但是当您使用OO存储框架来存储行为而不是数据时,情况总是如此。

答案 3 :(得分:0)

我在下面的类中有2个元素,其中一个是Stream,必须使用@JsonSerializer注释getterStream方法,然后重写Serialize方法,在我的Response API中生成JSON流:

公共类DataSetResultBean扩展ResultBean { 私有静态最终长serialVersionUID = 1L;

private final List<ComponentBean> structure;
private final Stream<DataPoint> datapoints;

private static class DataPointSerializer extends JsonSerializer<Stream<DataPoint>> 
{
    @Override
    public void serialize(Stream<DataPoint> stream, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException
    {
        gen.writeStartArray();
        try
        {
            stream.forEach(dp -> serializeSingle(gen, dp));
        }
        catch (UncheckedIOException e)
        {
            throw (IOException) e.getCause();
        }
        finally
        {
            stream.close();
        }
        gen.writeEndArray();
    }
    
    public synchronized void serializeSingle(JsonGenerator gen, DataPoint dp) throws UncheckedIOException
    {
        try
        {
            gen.writeStartObject();
            
            for (Entry<DataStructureComponent<?, ?, ?>, ScalarValue<?, ?, ?>> entry: dp.entrySet())
            {
                gen.writeFieldName(entry.getKey().getName());
                gen.writeRawValue(entry.getValue().toString());
            }
            
            gen.writeEndObject();
        }
        catch (IOException e)
        {
            throw new UncheckedIOException(e);
        }
    }
}

public DataSetResultBean(DataSet dataset)
{
    super("DATASET");
    
    structure = dataset.getMetadata().stream().map(ComponentBean::new).collect(toList());
    datapoints = dataset.stream();
}

public List<ComponentBean> getStructure()
{
    return structure;
}

@JsonSerialize(using = DataPointSerializer.class)
public Stream<DataPoint> getDatapoints()
{
    return datapoints;
}

}