java - Jackson Json,编码 ByteBuffer

标签 java json jackson

对于 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)

最佳答案

Jackson 在序列化具有大量内部状态和/或非标准 getter/setter 方法的复杂对象时通常会遇到问题。通常,您应该始终坚持要序列化的对象层次结构中的纯 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,但将其标记为 @JsonIgnoreable 并提供围绕它的替代访问器方法,将其转换为 byte[]

第一个例子:

class Wrapper {
    final byte[] buffer;

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

关于java - Jackson Json,编码 ByteBuffer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16606840/

相关文章:

java - 如何将两个相同的 json 属性名称分配给两个单独的字段

ios - SwiftyJSON 字典解析

java - 使用 ByteBuddy 重新定义 java.lang 类

java - 将 .cer 证书转换为 .jks

json - debugDescription : "Expected to decode Array<Any> but found a dictionary instead.", 底层错误:无)

java - Jackson 对象映射器如何忽略 JsonProperty 注释?

java - 如何使用 Jackson 将 JSON 数组序列化为编号/索引 JSON?

java - 使用 Jackson 在 Java 中序列化为 JSON 时出现问题

java - 如何对两个数组进行相互关联的排序?

java - 收起笨拙的 Java 类路径