【问题标题】:Jackson JSON - serialize StreamsJackson JSON - 序列化流
【发布时间】:2015-10-05 00:07:35
【问题描述】:

有没有办法让杰克逊序列化一些流对象(并在之后关闭)?像这样:

class TextFile{
    String fileName;
    StringReader content;
    //ByteArrayInputStream content;
}

更新

澄清:我想流式传输内容,而不仅仅是将其序列化为单个 String 对象。

【问题讨论】:

  • 流包含什么样的内容?你想把它写成base64吗?还是先解析它,然后写一些表示?
  • Base64 是一个选项,但不是必需的。我只是不想将整个字符串保存在内存中。

标签: java json jackson


【解决方案1】:

实现自定义JsonSerializer

public class StreamSerializer extends JsonSerializer<ByteArrayInputStream> {

    @Override
    public void serialize(ByteArrayInputStream content, 
                          JsonGenerator jsonGenerator, 
                          SerializerProvider serializerProvider) 
                          throws IOException, JsonProcessingException {
        jsonGenerator.writeBinary(content, -1);
}

并像这样使用它:

public class TextFile {
    String fileName;
    @JsonSerialize(using=StreamSerializer.class, as=byte[].class)
    ByteArrayInputStream content;
}

【讨论】:

  • 我不想将整个字符串对象保存在内存中。我会为此使用String content。问题是如何序列化流。
  • @kromit 这不在原始问题中!但是,我更新了我的答案。
  • 这就是我想要的。谢谢。
【解决方案2】:

您的问题类似于:Jackson JSON custom serialization for certain fields

期望的行为是什么?是否希望流被序列化为字符串、二进制内容、解析和序列化为对象等?

假设您希望将数据序列化为字符串,您可以使用注释告诉 Jackson 如何对其进行序列化:

public class TextFile {
    String fileName;
    @JsonSerialize(using=ReaderToStringSerializer.class, as=String.class)
    StringReader content;
}


public class ReaderToStringSerializer extends JsonSerializer<Reader> {

@Override
public void serialize(Reader contents, 
                      JsonGenerator jsonGenerator, 
                      SerializerProvider serializerProvider) 
                      throws IOException, JsonProcessingException {
    StringBuilder buffer = new StringBuilder();
    char[] array = new char[8096];
    int len = 0;
    while (-1 != (len = contents.read(array))) {
        buffer.append(array,0,len);
    }
    contents.close();
    jsonGenerator.writeString(buffer.toString());
}

输出将类似于:

{
  "fileName": "foo.bar",
  "content": "the quick brown fox..."
}

【讨论】:

  • 不要重蹈覆辙,使用commons-io的IOUtils#toString(Reader)获取Reader的内容为String
  • 这不会“流式传输”内容。 buffer.toString() 在内存中创建了整个字符串,并错过了首先使用流的全部意义。
  • 我假设您在内存中拥有全部数据,因为您在问题中指定了 StringReader。正确地流式传输 JSON 输出比读取字节和写入字节更困难,因为您必须正确考虑转义字符和不可打印字符。如果您想要 base64 输出,那么 writeBinary 解决方案(上图)是正确的。
  • @tombrown52 如何使用序列化程序将响应作为流(下载文件)而不是 json 格式发送? writeBinary 对此有用吗?
  • @xbmono 这整个线程非常依赖于 Jackson 库。因此,它主要适用于 JSON 格式,但可能适用于 Jackson 支持的任何其他格式(如 YAML)。 AFAIK Jackson API 要求您只编写完整的原始值(没有部分字符串)。但是,我认为 jsonGenerator 将输出一个标记流(整个值和单个语法字符,例如“}”)。我认为你不需要做任何特别的事情来从杰克逊那里获得这种流输出。如果您将您的问题作为一个实际的 SO 问题提出,我会尝试回答。
猜你喜欢
  • 2023-03-04
  • 2018-02-28
  • 2014-08-30
  • 2015-02-28
  • 2018-07-14
  • 1970-01-01
  • 1970-01-01
  • 2014-07-08
  • 2011-06-28
相关资源
最近更新 更多