计算 ObjectMapper 生成的 JSON 有效负载长度的最便宜方法

问题描述 投票:0回答:1

在我的应用程序中,我在进一步传递之前计算有效负载的长度(由

ObjectMapper
生成的 JSON)。

为了实现这一点,我使用自定义

OutputStream

@Autowired
ObjectMapper objectMapper;

private int calculateContentLength(MyPayload payload) throws IOException {
    var countingOutputStream = new CountingOutputStream();
    objectMapper.writeValue(countingOutputStream, accounts);
    return countingOutputStream.count;
}

private static class CountingOutputStream extends OutputStream {
    private int count;

    @Override
    public void write(int b) {
        count++;
    }

    @Override
    public void write(byte[] b) {
        count += b.length;
    }

    @Override
    public void write(byte[] b, int off, int len) {
        count += b.length;
    }
}

这工作得很好,但是需要一些额外的时间和内存来进行反序列化(

write(byte[] b, int off, int len)
方法接收长度为8192的
byte[]
)。

我想知道是否有其他更快的方法来实现这个?

java performance jackson objectmapper
1个回答
0
投票

如果您正在寻找一种更快、更节省内存的方法来计算 ObjectMapper 生成的 JSON 有效负载的长度,您可能需要考虑以下替代方案:

1。直接使用ObjectMapper

您可以将对象序列化为 byte[],然后获取其长度,而不是使用自定义 OutputStream:

private int calculateContentLength(MyPayload payload) throws IOException {
    byte[] jsonBytes = objectMapper.writeValueAsBytes(payload);
    return jsonBytes.length;
}

优点:

  • 简单:这种方法很简单,避免了自定义 OutputStream 的开销。
  • 内存高效:writeValueAsBytes 直接返回一个字节数组,您可以轻松测量该数组。

缺点:

  • 内存使用:此方法在内存中创建完整的字节数组,这对于非常大的有效负载可能是一个问题。

2。使用流式传输方法

如果您需要有效处理大型负载并避免将所有内容加载到内存中,您可以使用 Jackson 的 JsonGenerator 以流式传输方式估计长度。这种方法更复杂,但对于大负载来说内存效率更高。

private int calculateContentLength(MyPayload payload) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    JsonGenerator generator = objectMapper.getFactory().createGenerator(baos);
    objectMapper.writeValue(generator, payload);
    generator.close();
    return baos.size();
}

优点:

  • 流式处理:这种方法可以比创建完整字节数组更好地处理更大的有效负载。

缺点:

  • 复杂性:与 writeValueAsBytes 方法相比,实现起来更复杂。

3.具有优化写入方法的自定义输出流

如果您仍然喜欢使用自定义OutputStream,您可以通过更有效地实现写入方法来优化它:

private static class CountingOutputStream extends OutputStream {
    private long count;

    @Override
    public void write(int b) {
        count++;
    }

    @Override
    public void write(byte[] b) {
        count += b.length;
    }

    @Override
    public void write(byte[] b, int off, int len) {
        count += len;
    }

    public long getCount() {
        return count;
    }
}

优点:

  • 可定制:允许对计数行为进行细粒度控制。

缺点:

  • 开销:仍然涉及自定义实现,并且可能不如内置方法那么快。

总结

对于大多数情况,writeValueAsBytes 是最简单、最有效的方法。如果您正在处理非常大的有效负载并且需要最大限度地减少内存使用量,那么使用 JsonGenerator 的流式传输方法可能值得考虑。

© www.soinside.com 2019 - 2024. All rights reserved.