alex
alex

Reputation: 3442

Spring 3.2 and Jackson 2: add custom object mapper

I'm developing a REST webservice in spring MVC. I need to change how jackson 2 serialize mongodb objectids. I'm not sure of what to do because I found partial documentation for jackson 2, what I did is to create a custom serializer:

public class ObjectIdSerializer extends JsonSerializer<ObjectId> {


    @Override
    public void serialize(ObjectId value, JsonGenerator jsonGen,
            SerializerProvider provider) throws IOException,
            JsonProcessingException {
        jsonGen.writeString(value.toString());
    }
}

Create a ObjectMapper

public class CustomObjectMapper extends ObjectMapper {

    public CustomObjectMapper() {
        SimpleModule module = new SimpleModule("ObjectIdmodule");
        module.addSerializer(ObjectId.class, new ObjectIdSerializer());
        this.registerModule(module);
    }

}

and then register the mapper

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <bean
            class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="my.package.CustomObjectMapper"></bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

My CustomConverter is never called. I think the CustomObjectMapper definition is wrong,I adapted it from some code for jackson 1.x

In my controllers I'm using @ResponseBody. Where am I doing wrong? Thanks

Upvotes: 14

Views: 13872

Answers (3)

Varun Sood
Varun Sood

Reputation: 221

There is no need to create object mapper. Add jackson-core-2.0.0.jar and jackson-annotations-2.0.0.jar to your project.

Now, add the following lines of code to your controller while handing the service:

@RequestMapping(value = "students", method = RequestMethod.POST, headers = "Accept=application/json", consumes = "application/json")

public HashMap<String, String> postStudentForm(
            @RequestBody Student student, HttpServletResponse response)

Do not miss any of the annotations.

Upvotes: 0

Taras
Taras

Reputation: 322

You should annotate corresponding model field with @JsonSerialize annontation. In your case it may be:

public class MyMongoModel{
   @JsonSerialize(using=ObjectIdSerializer.class)
   private ObjectId id;
}

But in my opinion, it should better don't use entity models as VOs. Better way is to have different models and map between them. You can find my example project here (I used date serialization with Spring 3 and Jackson 2 as example).

Upvotes: 4

ninnemannk
ninnemannk

Reputation: 1296

How I would do this is:

Create an annotation to declare your custom serializers:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyMessageConverter{
}

Set up component scan for this in your mvcconfiguration file

<context:include-filter expression="package.package.MyMessageConverter"
            type="annotation" />

and create a class that implements HttpMessageConverter<T>.

@MyMessageConverter
public MyConverter implements HttpMessageConverter<T>{
//do everything that's required for conversion.
}

Create a class that extends AnnotationMethodHandlerAdapter implements InitializingBean.

    public MyAnnotationHandler extends AnnotationMethodHandlerAdapter implements InitializingBean{
    //Do the stuffs you need to configure the converters
    //Scan for your beans that have your specific annotation
    //get the list of already registered message converters
    //I think the list may be immutable. So, create a new list, including all of the currently configured message converters and add your own. 
    //Then, set the list back into the "setMessageConverters" method.
    }

I believe this is everything that is required for your goal.

Cheers.

Upvotes: 0

Related Questions