Jackson ObjectMapper using custom Serializers and Deserializers

deserialization, jackson, java, serialization, testing

Solution

From the answers & comments provided here, I recently redesigned the class to use builders for both the `Module` and the `ObjectMapper`. This allowed me to provide mocks and check that the correct (de)serializers were added to the module and then the module is registered to the object mapper as expected.

Object Mapper Builder:

public class ObjectMapperBuilder {
    ObjectMapper mapper;

    public ObjectMapperBuilder configure(final ObjectMapper mapper) {
        this.mapper = mapper;
        return this;
    }

    public ObjectMapperBuilder withModule(final Module module) {
        this.mapper.registerModule(module);
        return this;
    }

    public ObjectMapper build() {
        return this.mapper;
    }
}

Module Builder:

public class SimpleModuleBuilder {
    SimpleModule module;

    public SimpleModuleBuilder configure(final SimpleModule module) {
        this.module = module;
        return this;
    }

    public <X> SimpleModuleBuilder withSerializer(final Class<X> clazz, final JsonSerializer<X> serializer) {
        this.module.addSerializer(clazz, serializer);
        return this;
    }

    public <X> SimpleModuleBuilder withDeserializer(final Class<X> clazz, final JsonDeserializer<X> deserializer) {
        this.module.addDeserializer(clazz, deserializer);
        return this;
    }

    public SimpleModule build() {
        return this.module;
    }
}

And finally, the new JsonMapperFactory:

public class JsonMapperFactory {

    public static ObjectMapper configureObjectMapper(final ObjectMapper mapper, final SimpleModule module) {
        final SimpleModuleBuilder modulebuilder = new SimpleModuleBuilder();

        final SimpleModule configuredModule = modulebuilder.configure(module)
            .withSerializer(DateTime.class, new DateTimeSerializer())
            .withDeserializer(DateTime.class, new DateTimeDeserializer())
            .build();

        final ObjectMapperBuilder objectMapperBuilder = new ObjectMapperBuilder();
        return objectMapperBuilder.configure(mapper).withModule(configuredModule).build();
    }
}

The factory method is still used within Spring configuration, but the configuration now instantiates the blank `Module` and `ObjectMapper` before providing them to the factory methods that then configure them.

Problem

I've got a class that configures a Jackson ObjectMapper. It adds in some custom serializers and deserializers for my object types as follows: ``` public class JsonMapperFactory { public static ObjectMapper createObjectMapper() { final SimpleModule module = new SimpleModule("customerSerializationModule", new Version(1, 0, 0, "static version")); addCustomDeserializersTo(module); addCustomSerializersTo(module); final ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(module); return objectMapper; } private static void addCustomSerializersTo(final SimpleModule module) { module.addSerializer(DateTime.class, new DateTimeSerializer()); } private static void addCustomDeserializersTo(final SimpleModule objectMapper) { objectMapper.addDeserializer(DateTime.class, new DateTimeDeserializer()); } } ``` I've tested my customer serializers within their own test classes, so in my test of this `JsonMapperFactory` class, I'm trying to simply check that the ObjectMapper created has the expected serializers (or deserializers) This could be achieve by introspecting the ObjectMapper, but it doesn't seem to have any mechanisms to do this. Does anyone know of a nice way to test that? For deserializers, I have the following: ``` private void assertThatObjectMapperUsesCorrectDeserializer(final Class<?> typeClazz, final Class<?> deserializerClazz) throws JsonMappingException { final DeserializationConfig deserializationConfig = this.objectMapper.getDeserializationConfig(); final JsonDeserializer<Object> deserializer = this.objectMapper.getDeserializerProvider().findTypedValueDeserializer(deserializationConfig, javaTypeFor(typeClazz), null); assertThat(deserializer, is(instanceOf(deserializerClazz))); } private JavaType javaTypeFor(final Class<?> clazz) { return TypeFactory.type(clazz); //deprecated method :( } ``` Which is quite verbose and uses deprecated methods. I'm yet to find a way to do a similar test for the serializers. So I've currently resorted to serializing an object and check it serializes correctly (essentially duplicating the serializer test) Any ideas are very welcome.

Original source