21

由于对 Spring 还有些陌生,我遇到了一个问题,需要为 Jackson 实现我的自定义解串器。该过程在一个小教程中进行了描述,但是,我坚持使用 Spring。不明白,在哪里

 ObjectMapper mapper = new ObjectMapper();

在 Spring MVC 中,当通过控制器类的方法反序列化 json 时执行。所以我不知道该怎么做才能用自定义反序列化器替换默认反序列化器。

欢迎提出任何建议。

4

6 回答 6

20

你没有说你在 Spring 中是如何使用 Jackson 的,所以我假设你是通过和/或注释来使用<mvc:annotation-driven/>@RequestBody@ResponseBody

其中一件事<mvc:annotation-driven/>是注册一个AnnotationMethodHandlerAdapter带有许多预配置HttpMessageConverterbean 的 bean,其中包括MappingJacksonHttpMessageConverter处理与 Jackson 注释的模型类之间的编组。

现在MappingJacksonHttpMessageConverter有一个setObjectMapper()方法,它允许您覆盖默认的ObjectMapper. 但是由于MappingJacksonHttpMessageConverter是由 幕后创建的<mvc:annotation-driven/>,因此您无法访问它。

然而,<mvc:annotation-driven/>这只是一个方便的捷径。声明您自己的AnnotationMethodHandlerAdapterbean,将您自己的MappingJacksonHttpMessageConverterbean(通过messageConverters属性)注入其中,然后将您自己的定制ObjectMapper注入其中,这同样有效。

然后你就会遇到如何构建 custom 的问题ObjectMapper,因为它不是一个对 Spring 非常友好的类。我建议编写自己的简单实现FactoryBean.

所以你最终会得到这样的东西:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
   <property name="messageConverters">
      <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
         <property name="objectMapper">
            <bean class="com.x.MyObjectMapperFactoryBean"/>
         </property>
      </bean>
   </property>
</bean>
于 2010-08-30T17:25:07.570 回答
7

在 Spring 3.1 中执行此操作的新方法:http:
//magicmonster.com/kb/prg/java/spring/webmvc/mvc_spring_config_namespace.html

http://blog.springsource.org/2011/02/21/spring-3-1-m1-mvc-namespace-enhancements-and-configuration/

允许您执行以下操作:

<mvc:annotation-driven>
      <mvc:message-converters>
          <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
              <property name="objectMapper" ref="customObjectMapper"/>
          </bean>
      </mvc:message-converters>
  </mvc:annotation-driven>
于 2013-01-23T21:59:48.200 回答
5

Rakesh 引用的解决方案可能适用于 Spring MVC 3.0,但在 3.1 中,一些 MVC 基础结构发生了变化。因此,您可能没有AnnotationMethodHandlerAdapter在应用程序上下文中注册 bean,并且您最终会BeanCreationException在初始化时得到一个 at 。

对于 Spring MVC 3.1,该mvc:annotation-driven元素将为您创建一个RequestMappingHandlerAdapter,因此您应该改为自动装配该类型。它仍将提供对已注册 HttpMessageConverters 列表的访问权限,并允许您在MappingJacksonHttpMessageConverter. 这也需要在init. HttpMessageConverters 引用类型的方法。

更新后的类如下所示:

@Component
public class JacksonFix {
    private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
    private CustomObjectMapper objectMapper;

    @PostConstruct
    public void init() {
        List<HttpMessageConverter<?>> messageConverters = requestMappingHandlerAdapter.getMessageConverters();
        for (HttpMessageConverter<?> messageConverter : messageConverters) {
            if (messageConverter instanceof MappingJacksonHttpMessageConverter) {
                MappingJacksonHttpMessageConverter m = (MappingJacksonHttpMessageConverter) messageConverter;
                m.setObjectMapper(objectMapper);
            }
        }
    }

    // this will exist due to the <mvc:annotation-driven/> bean
    @Autowired
    public void setRequestMappingHandlerAdapter(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {
        this.requestMappingHandlerAdapter = requestMappingHandlerAdapter;
    }

    @Autowired
    public void setObjectMapper(CustomObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }
}

更新:事实证明,使用 Spring 3.1 做的最简单的事情是在 MVC 配置中添加一些额外的配置:

<mvc:annotation-driven conversion-service="applicationConversionService">
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
            <property name="objectMapper" ref="customObjectMapper" />
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

这将MappingJacksonHttpMessageConverter在任何默认 HttpMessageConverters 之前添加一个带有自定义 ObjectMapper 的新实例(由于 HttpMessageConverters 仍然存在register-defaults="true")。

于 2012-08-04T03:58:49.633 回答
2

就我而言(Spring 3.2.4 和 Jackson 2.3.1),自定义序列化程序的 XML 配置:

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="false">
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                    <property name="serializers">
                        <array>
                            <bean class="com.example.business.serializer.json.CustomObjectSerializer"/>
                        </array>
                    </property>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

以无法解释的方式被某些东西覆盖回默认值。

这对我有用:

自定义对象.java

@JsonSerialize(using = CustomObjectSerializer.class)
public class CustomObject {

    private Long value;

    public Long getValue() {
        return value;
    }

    public void setValue(Long value) {
        this.value = value;
    }
}

CustomObjectSerializer.java

public class CustomObjectSerializer extends JsonSerializer<CustomObject> {

    @Override
    public void serialize(CustomObject value, JsonGenerator jgen,
        SerializerProvider provider) throws IOException,JsonProcessingException {
        jgen.writeStartObject();
        jgen.writeNumberField("y", value.getValue());
        jgen.writeEndObject();
    }

    @Override
    public Class<CustomObject> handledType() {
        return CustomObject.class;
    }
}

<mvc:message-converters>(...)</mvc:message-converters>我的解决方案中不需要 XML 配置 ( )。

于 2014-02-12T11:20:14.350 回答
0

我希望我更了解 Spring MVC,但是对于像 Jersey 和 RESTeasy 这样的 Jax-RS 实现,一个注册提供程序。也许 Spring 会做类似的事情?

于 2010-08-30T17:13:11.210 回答
0

MappingJacksonHttpMessageConverter 状态的春季文档:

2.4.5 映射JacksonHttpMessageConverter

可以使用 Jackson JSON 处理器的 ObjectMapper 读取和写入 JSON 的 HttpMessageConverter 实现。JSON 映射可以通过使用 Jackson 提供的注释根据需要进行自定义。当需要进一步控制时,可以通过 ObjectMapper 属性注入自定义 ObjectMapper,以应对需要为特定类型提供自定义 JSON 序列化器/反序列化器的情况。默认情况下,此转换器支持 (application/json)。

难道你不能自动访问 ObjectMapper 来修改它的行为吗?

于 2011-10-23T15:10:27.013 回答