Jackson Json,将ByteBuffer转换为JSON字符串

4

在 ByteBuffer 中,是否有最小数据大小的限制,以便Jackson能够对其进行序列化? 当数据大小较小时,我会遇到BufferUnderflowException错误。但当数据大小较大时则可正常工作。

public class MyTest {
    private static class Wrapper {
        private ByteBuffer buffer;
        public void setBuffer(ByteBuffer buffer) {
            this.buffer = buffer;
        }
        public ByteBuffer getBuffer() {
            return buffer;
        }
    }

    @Test
    public void fails() throws Exception {
        // Fails
        ByteBuffer smallBuffer = ByteBuffer.wrap("small".getBytes());
        Wrapper wrapper1 = new Wrapper();
        wrapper1.setBuffer(smallBuffer);
        System.out.println(new ObjectMapper().writeValueAsBytes(wrapper1));
    }

    @Test
    public void works() throws Exception {
        // Works
        ByteBuffer smallBuffer = ByteBuffer.wrap("larger string works, wonder why".getBytes());
        Wrapper wrapper1 = new Wrapper();
        wrapper1.setBuffer(smallBuffer);
        System.out.println(new ObjectMapper().writeValueAsBytes(wrapper1));
    }

}

异常堆栈:

org.codehaus.jackson.map.JsonMappingException: (was java.nio.BufferUnderflowException) (through reference chain: com.test.Wrapper["buffer"]->java.nio.HeapByteBuffer["int"])
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:218)
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:183)
    at org.codehaus.jackson.map.ser.std.SerializerBase.wrapAndThrow(SerializerBase.java:140)
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:158)
1个回答

6

当序列化具有许多内部状态和/或非标准getter/setter方法的复杂对象时,Jackson通常会遇到问题。一般情况下,您应始终坚持将纯POJO用于要序列化的对象层次结构。

在这种特殊情况下,您创建了一个包含ByteBuffer的包装器。实际上,Jackson尝试对整个字节缓冲区对象进行序列化(而不仅仅是其字节内容),如果您深入了解,它实际上试图编写所有这些“属性”:

[
    property 'short' (via method java.nio.HeapByteBuffer#getShort), 
    property 'char' (via method java.nio.HeapByteBuffer#getChar),
    property 'int' (via method java.nio.HeapByteBuffer#getInt),
    property 'long' (via method java.nio.HeapByteBuffer#getLong),
    property 'float' (via method java.nio.HeapByteBuffer#getFloat),
    property 'double' (via method java.nio.HeapByteBuffer#getDouble),
    property 'direct' (via method java.nio.HeapByteBuffer#isDirect),
    property 'readOnly' (via method java.nio.HeapByteBuffer#isReadOnly)
]

仅仅是因为运气好,第二种情况才能够工作(因为缓冲区足够长,可以在不下溢的情况下调用上述所有方法)。如果您想将缓冲区序列化为字节,则可以:

  • 将包装器属性更改为byte[]
  • 保持属性为ByteBuffer,但标记它为@JsonIgnore并提供一个替代访问器方法,该方法将其转换为byte[]

第一种情况的示例:

class Wrapper {
    final byte[] buffer;

    public Wrapper(final ByteBuffer buffer) {
        super();
        this.buffer = buffer != null ? buffer.array() : new byte[0];
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接