2013-05-17 5 views
2

Есть ли ограничение на минимальный размер данных, которые должны присутствовать в ByteBuffer, чтобы Джексон смог его сериализовать? При этом я получаю 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)); 
    } 

} 

Исключение трассировки стека:

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