4

Is there any restriction on the minimum size of the data that should be present in ByteBuffer so that Jackson will be able to serialize it ? I get BufferUnderflowException while doing so. But it works fine when the size of data present is large.

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));
    }

}

Exception stack trace:

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)
4

1 回答 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,但将其标记为@JsonIgnoreable 并在其周围提供一个替代访问器方法,该方法转换为byte[]

第一个例子:

class Wrapper {
    final byte[] buffer;

    public Wrapper(final ByteBuffer buffer) {
        super();
        this.buffer = buffer != null ? buffer.array() : new byte[0];
    }
}
于 2013-05-17T11:07:04.247 回答