Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 381
fge Avatar asked Oct 31 '14 10:10

fge


1 Answers

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

    }

}
like image 187
Thomas Maurel Avatar answered Sep 22 '22 07:09

Thomas Maurel