由于对 Spring 还有些陌生,我遇到了一个问题,需要为 Jackson 实现我的自定义解串器。该过程在一个小教程中进行了描述,但是,我坚持使用 Spring。不明白,在哪里
ObjectMapper mapper = new ObjectMapper();
在 Spring MVC 中,当通过控制器类的方法反序列化 json 时执行。所以我不知道该怎么做才能用自定义反序列化器替换默认反序列化器。
欢迎提出任何建议。
你没有说你在 Spring 中是如何使用 Jackson 的,所以我假设你是通过和/或注释来使用<mvc:annotation-driven/>
它@RequestBody
的@ResponseBody
。
其中一件事<mvc:annotation-driven/>
是注册一个AnnotationMethodHandlerAdapter
带有许多预配置HttpMessageConverter
bean 的 bean,其中包括MappingJacksonHttpMessageConverter
处理与 Jackson 注释的模型类之间的编组。
现在MappingJacksonHttpMessageConverter
有一个setObjectMapper()
方法,它允许您覆盖默认的ObjectMapper
. 但是由于MappingJacksonHttpMessageConverter
是由 幕后创建的<mvc:annotation-driven/>
,因此您无法访问它。
然而,<mvc:annotation-driven/>
这只是一个方便的捷径。声明您自己的AnnotationMethodHandlerAdapter
bean,将您自己的MappingJacksonHttpMessageConverter
bean(通过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>
在 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>
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"
)。
就我而言(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>
以无法解释的方式被某些东西覆盖回默认值。
这对我有用:
@JsonSerialize(using = CustomObjectSerializer.class)
public class CustomObject {
private Long value;
public Long getValue() {
return value;
}
public void setValue(Long value) {
this.value = value;
}
}
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 配置 ( )。
我希望我更了解 Spring MVC,但是对于像 Jersey 和 RESTeasy 这样的 Jax-RS 实现,一个注册提供程序。也许 Spring 会做类似的事情?
MappingJacksonHttpMessageConverter 状态的春季文档:
2.4.5 映射JacksonHttpMessageConverter
可以使用 Jackson JSON 处理器的 ObjectMapper 读取和写入 JSON 的 HttpMessageConverter 实现。JSON 映射可以通过使用 Jackson 提供的注释根据需要进行自定义。当需要进一步控制时,可以通过 ObjectMapper 属性注入自定义 ObjectMapper,以应对需要为特定类型提供自定义 JSON 序列化器/反序列化器的情况。默认情况下,此转换器支持 (application/json)。
难道你不能自动访问 ObjectMapper 来修改它的行为吗?