How to trigger calls to .serializeWithType() of a class implementing JsonSerializable in Jackson?

会有一股神秘感。 提交于 2019-12-22 04:51:18

问题


This is Jackson 2.2.x.

I have a class implementing JsonSerializable; there are two methods to implement for this interface, serialize() and serializeWithType().

I want to test {de,}serialization of this class, and I can trigger calls to serialize() easily; not, however, serializeWithType().

The javadoc for this latter method says that this method is called

[...] when additional type information is expected to be included in serialization, for deserialization to use.

I just don't understand what this means...

How do I set up a test environment so that this method be called? Note that the JSON to be serialized can be of any type except object (ie, boolean, number, string, array are all valid types).


回答1:


This method is used when you want to use polymorphism

public class A {
    ...
}

public class B extends A {
    ...
}

public class C extends A {
    ...
}

If you serialize an instance of C and then try to deserialize the resulting json but only knowing that its a sub-type of A :

final ObjectMapper objectMapper = new ObjectMapper();
final String json = objectMapper.writeValueAsString(new C());
final A deserialized = objectMapper.readValue(json, A.class);

You need something to be stored within the resulting JSON to keep the real type of the serialized object.

This can be enabled either using @JsonTypeInfo on your class, or by calling enableDefaultTyping on your ObjectMapper.

This is a sample test case using JUnit & Mockito

import com.fasterxml.jackson.databind.JsonSerializable;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

public class SerializeWithTypeTest {

    private JsonSerializable serializable = mock(JsonSerializable.class);

    @Test
    public void shouldCallSerializeWithType() throws Exception {
        final ObjectMapper objectMapper = new ObjectMapper().enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        objectMapper.writeValueAsString(serializable);

        // make sure serializeWithType is called once
        verify(serializable, times(1)).serializeWithType(any(), any(), any());

    }

}



回答2:


Jackson 2 is completely incompatible with Jackson 1, and JsonSerializableWithType (Now deprecated and unusable) is an interface from Jackson 1 which led to the presence of serializeWithType() in Jackson 2.

serializeWithType() is called when additional type information is expected to be included, which means that an annotation (JsonTypeInfo) is specifying the class property for deserialization delegation, when polymorphism is used. This method will then be called with the additional type information within a TypeSerializer, which may be written with a type prefix:

/* (.., .., TypeSerializer typeSer) */ {
    typeSer.writeTypePrefixForScalar(.., .., ThisClass.class);
}

By annotating the class with @JsonTypeInfo, you will be able to specify serializing with the type information:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
        include = As.WRAPPER_OBJECT,
        property = "type")
@JsonSubTypes({
        @Type(name = "typeint", value = MyInt.class),
        @Type(name = "typefloat", value = MyFloat.class)
})
public interface MyNumber {}

@JsonTypeName("typeint")
public MyInt implements MyNumber {}

@JsonTypeName("typefloat")
public MyFloat implements MyNumber {}

Then the values typeint and typefloat will be set in the property named type. When you deserialize a MyNumber, it will be based on polymorphism. Thomas Maurel's answer demonstrates a straightforward approach to test by serializing the object as string and deseralizing it.




回答3:


Try to use JsonTypeInfo annotation on your class. It should trigger calling serializeWithType(). It is used to store info about type which is required for polymorphic types or to link abstract type and matching concrete implementation.



来源:https://stackoverflow.com/questions/26672297/how-to-trigger-calls-to-serializewithtype-of-a-class-implementing-jsonseriali

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!