4

Jackson がシリアル化できるように、ByteBuffer に存在するデータの最小サイズに制限はありますか? そうしている間に 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)
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)
]

2 番目のケースが機能するのはばかげた運によるものです (バッファーは、上記のすべてのメソッドをアンダーフローせずに呼び出すのに十分な長さであるため)。バッファをバイトとしてシリアル化する場合は、次のいずれかを行います。

  • ラッパー プロパティを次のように変更します。byte[]
  • プロパティを のままにしますがByteBuffer、それを可能としてマークし、@JsonIgnoreそれに変換する代替アクセサ メソッドを提供します。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 に答える