2013-05-17 48 views
2

對ByteBuffer中應該存在的數據的最小大小是否有任何限制,以便Jackson能夠序列化它?這樣做的時候我得到了BufferUnderflowException。 但是,當數據大小很大時,它工作正常。Jackson Json,編組ByteBuffer

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

} 

異常堆棧跟蹤:有很多內部狀態和/或非標準的getter/setter方法的序列化複雜的對象時

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) 

回答

5

傑克遜通常會遇到的問題。通常,您應該始終堅持對象層次結構中的純POJO進行序列化。

在這種特殊情況下,您創建了一個包含ByteBuffer的包裝器。那麼,傑克遜實際上是嘗試序列化整個字節的緩衝區對象(不只是它的字節內容),如果你看一下在幕後它實際上是試圖寫出所有這些「特性」:

[ 
    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]; 
    } 
}