14

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

Maurice Perry
  • 32,610
  • 9
  • 70
  • 97
alex
  • 3,412
  • 2
  • 28
  • 36
  • 2
    Serializer and registration look correct to me, so I think the problem lies in xml configuration. – StaxMan Jan 16 '13 at 21:18
  • 1
    Yep, thanks for the suggestion, I had an empty tag around the file. It's working now – alex Jan 16 '13 at 21:52
  • FYI the docs say to use StdSerializer instead: http://fasterxml.github.io/jackson-databind/javadoc/2.0.0/com/fasterxml/jackson/databind/ser/std/StdSerializer.html – testing123 Jun 05 '13 at 05:29
  • I'm having a similar issue. Can you please post your final working solution? – Eric B. Dec 19 '13 at 19:51
  • In my project we extends StdSerializer instead of JsonSerializer, but that is not the problem. Be sure that you use com.fasterxml.* classes and not old org.codehaus.* classes? – pdem Mar 12 '14 at 13:03
  • Try changing `register-defaults="true"` to `register-defaults="false"` – Marlon Bernardes May 14 '14 at 12:18
  • @alex, can you please post the total solution? – sendreams May 16 '14 at 05:00
  • This is the code i used https://gist.github.com/alexmazza/f61aa2a72e9f725c2ef8 It's basically the same that I posted here, the problem was in the xml configuration, I had a double tag that was messing things – alex May 16 '14 at 13:02

3 Answers3

4

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

Taras
  • 312
  • 3
  • 7
0

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.

ninnemannk
  • 1,296
  • 1
  • 14
  • 26
0

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.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Varun Sood
  • 201
  • 1
  • 3
  • 8