Spring 3.2 и Jackson 2: добавить настраиваемый объект mapper

Я разрабатываю веб-сервис REST в spring MVC. Мне нужно изменить, как jackson 2 сериализует объектные объекты mongodb. Я не уверен, что делать, потому что я нашел частичную документацию для jackson 2, что я сделал, чтобы создать собственный сериализатор:

public class ObjectIdSerializer extends JsonSerializer<ObjectId> {


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

Создайте ObjectMapper

public class CustomObjectMapper extends ObjectMapper {

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

}

а затем зарегистрировать 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>

Мой CustomConverter никогда не вызывается. Я думаю, что определение CustomObjectMapper неверно, я адаптировал его из некоторого кода для jackson 1.x

В моих контроллерах я использую @ResponseBody. Где я поступаю неправильно? Благодаря

Ответ 1

Вы должны аннотировать соответствующее поле модели с помощью @JsonSerialize аннотации. В вашем случае это может быть:

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

Но, на мой взгляд, лучше не использовать модели сущностей в качестве VO. Лучше всего иметь разные модели и отображать их между собой. Здесь вы можете найти мой пример проекта (я использовал сериализацию даты с помощью Spring 3 и Jackson 2 в качестве примера).

Ответ 2

Как бы я это сделал:

Создайте аннотацию для объявления своих пользовательских сериализаторов:

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

Настройте проверку компонента для этого в файле mvcconfiguration

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

и создайте класс, который реализует HttpMessageConverter<T>.

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

Создайте класс, который 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.
    }

Я считаю, что это все, что требуется для вашей цели.

Приветствия.

Ответ 3

Нет необходимости создавать объект mapper. Добавьте к вашему проекту jackson-core-2.0.0.jar и jackson-annotations-2.0.0.jar.

Теперь добавьте следующие строки кода к контроллеру при передаче службы:

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

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

Не пропустите ни одной из аннотаций.