json Spring、Jackson 和自定义(例如 CustomDeserializer)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3591291/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring, Hymanson and Customization (e.g. CustomDeserializer)
提问by Ta Sas
Being still a little unfamiliar with Spring, I have encountered a problemthat makes it necessary implementing my a custom deserialzer for Hymanson. The procedure is described in a small tutorial, however, I am stuck with Spring. I do not understand, where
由于对 Spring 仍然有点陌生,我遇到了一个问题,因此有必要为 Hymanson 实现我的自定义反序列化器。该过程在一个小教程中进行了描述,但是,我坚持使用 Spring。我不明白,在哪里
ObjectMapper mapper = new ObjectMapper();
in Spring MVC is carried out when json is deserializes by a method of a controller class. So I do not know, what to do in order to replace the default deserializer by a custom deserialiser.
在 Spring MVC 中,当 json 通过控制器类的方法反序列化时执行。所以我不知道该怎么做才能用自定义解串器替换默认解串器。
Any suggestions most welcome.
任何建议最欢迎。
采纳答案by skaffman
You don't say how you're using Hymanson in Spring, so I'll assume you're using it through <mvc:annotation-driven/>and the @RequestBodyand/or @ResponseBodyannotations.
你没有说你在 Spring 中如何使用 Hymanson,所以我假设你是通过<mvc:annotation-driven/>和@RequestBody和/或@ResponseBody注释来使用它的。
One of the things that <mvc:annotation-driven/>does is to register a AnnotationMethodHandlerAdapterbean which comes with a number of pre-configured HttpMessageConverterbeans, including MappingHymansonHttpMessageConverter, which handles marshalling to and from Hymanson-annotated model classes.
要做的事情之一<mvc:annotation-driven/>是注册一个AnnotationMethodHandlerAdapterbean,该bean 带有许多预配置的HttpMessageConverterbean,包括MappingHymansonHttpMessageConverter,它处理与 Hymanson 注释的模型类之间的编组。
Now MappingHymansonHttpMessageConverterhas a setObjectMapper()method, which allows you to override the default ObjectMapper. But since MappingHymansonHttpMessageConverteris created behind the scenes by <mvc:annotation-driven/>, you can't get to it.
现在MappingHymansonHttpMessageConverter有一个setObjectMapper()方法,它允许您覆盖默认的ObjectMapper. 但是由于MappingHymansonHttpMessageConverter是由 幕后创建的<mvc:annotation-driven/>,您无法访问它。
However, <mvc:annotation-driven/>is just a convenient short-cut. It's just as a valid to declare your own AnnotationMethodHandlerAdapterbean, injecting into it your own MappingHymansonHttpMessageConverterbean (via the messageConvertersproperty), and injecting your own customized ObjectMapperinto that.
然而,<mvc:annotation-driven/>只是一个方便的捷径。声明您自己的AnnotationMethodHandlerAdapterbean,将您自己的MappingHymansonHttpMessageConverterbean(通过messageConverters属性)注入其中,并将您自己的定制ObjectMapper注入其中,这同样有效。
You then have the problem of how to build a custom ObjectMapper, since it's not a very Spring-friendly class. I suggest writing your own simple implementation of FactoryBean.
然后您会遇到如何构建 custom 的问题ObjectMapper,因为它不是一个非常适合 Spring 的类。我建议自己FactoryBean编写简单的.
So you'd end up with something like this:
所以你最终会得到这样的结果:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<bean class="org.springframework.http.converter.json.MappingHymansonHttpMessageConverter">
<property name="objectMapper">
<bean class="com.x.MyObjectMapperFactoryBean"/>
</property>
</bean>
</property>
</bean>
回答by Ryan Walls
New way to do this in Spring 3.1:
http://magicmonster.com/kb/prg/java/spring/webmvc/mvc_spring_config_namespace.html
在 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/
http://blog.springsource.org/2011/02/21/spring-3-1-m1-mvc-namespace-enhancements-and-configuration/
Allows you to do something like this:
允许你做这样的事情:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingHymansonHttpMessageConverter">
<property name="objectMapper" ref="customObjectMapper"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
回答by kylesm
The solution referenced by Rakesh likely works with Spring MVC 3.0 but with 3.1 some of the MVC infrastructure has changed. As a result you may not have an AnnotationMethodHandlerAdapterbean registered in your application context and you'll end up with a BeanCreationExceptionat initialization time.
Rakesh 引用的解决方案可能适用于 Spring MVC 3.0,但在 3.1 中,某些 MVC 基础结构发生了变化。因此,您可能没有AnnotationMethodHandlerAdapter在应用程序上下文中注册 bean,最终会BeanCreationException在初始化时得到 。
For Spring MVC 3.1 the mvc:annotation-drivenelement will create a RequestMappingHandlerAdapterfor you, so you should autowire that type instead. It will still provide access to the list of registered HttpMessageConverters and allow you to set the ObjectMapper property on the MappingHymansonHttpMessageConverter. This also requires a slight change within the init. method to the type of the HttpMessageConverters reference.
对于 Spring MVC 3.1,该mvc:annotation-driven元素将为您创建一个RequestMappingHandlerAdapter,因此您应该改为自动装配该类型。它仍将提供对已注册 HttpMessageConverters 列表的访问,并允许您在MappingHymansonHttpMessageConverter. 这也需要在init. HttpMessageConverters 引用类型的方法。
The updated class looks like:
更新后的类如下所示:
@Component
public class HymansonFix {
private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
private CustomObjectMapper objectMapper;
@PostConstruct
public void init() {
List<HttpMessageConverter<?>> messageConverters = requestMappingHandlerAdapter.getMessageConverters();
for (HttpMessageConverter<?> messageConverter : messageConverters) {
if (messageConverter instanceof MappingHymansonHttpMessageConverter) {
MappingHymansonHttpMessageConverter m = (MappingHymansonHttpMessageConverter) 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;
}
}
UPDATE: It turns out the absolute easiest thing to do with Spring 3.1 is to add some additional configuration to your MVC configuration:
更新:事实证明,使用 Spring 3.1 做的最简单的事情是向您的 MVC 配置添加一些额外的配置:
<mvc:annotation-driven conversion-service="applicationConversionService">
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.json.MappingHymansonHttpMessageConverter">
<property name="objectMapper" ref="customObjectMapper" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
That will add a new instance of MappingHymansonHttpMessageConverterwith the custom ObjectMapper before any of the default HttpMessageConverters (which are still present due to register-defaults="true").
这将MappingHymansonHttpMessageConverter在任何默认 HttpMessageConverters(由于 仍然存在register-defaults="true")之前添加一个带有自定义 ObjectMapper的新实例。
回答by user11153
In my case (Spring 3.2.4 and Hymanson 2.3.1), XML configuration for custom serializer:
就我而言(Spring 3.2.4 和 Hymanson 2.3.1),自定义序列化程序的 XML 配置:
<mvc:annotation-driven>
<mvc:message-converters register-defaults="false">
<bean class="org.springframework.http.converter.json.MappingHymanson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Hymanson2ObjectMapperFactoryBean">
<property name="serializers">
<array>
<bean class="com.example.business.serializer.json.CustomObjectSerializer"/>
</array>
</property>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
was in unexplained way overwritten back to default by something.
以无法解释的方式被某些东西覆盖回默认值。
This worked for me:
这对我有用:
CustomObject.java
自定义对象.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
自定义对象序列化器.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;
}
}
No XML configuration (<mvc:message-converters>(...)</mvc:message-converters>) is needed in my solution.
<mvc:message-converters>(...)</mvc:message-converters>我的解决方案中不需要 XML 配置 ( )。
回答by Bruce Edge
The spring docs for MappingHymansonHttpMessageConverter state:
MappingHymansonHttpMessageConverter 状态的 spring 文档:
2.4.5 MappingHymansonHttpMessageConverter
2.4.5 映射HymansonHttpMessageConverter
An HttpMessageConverter implementation that can read and write JSON using Hymanson JSON Processor's ObjectMapper. JSON mapping can be customized as needed through the use of Hymanson's provided annotations. When further control is needed, a custom ObjectMapper can be injected through the ObjectMapper property for cases where custom JSON serializers/deserializers need to be provided for specific types. By default this converter supports (application/json).
一个 HttpMessageConverter 实现,可以使用 Hymanson JSON Processor 的 ObjectMapper 读取和写入 JSON。JSON 映射可以根据需要通过使用 Hymanson 提供的注释进行自定义。当需要进一步控制时,可以通过 ObjectMapper 属性注入自定义 ObjectMapper,用于需要为特定类型提供自定义 JSON 序列化器/反序列化器的情况。默认情况下,此转换器支持 (application/json)。
Couldn't you just autowire access to the ObjectMapper in order to modify it's behaviour?
你不能只是自动连接对 ObjectMapper 的访问以修改它的行为吗?
回答by StaxMan
I wish I knew Spring MVC better, but with Jax-RS implementations like Jersey and RESTeasy, one registers providers. Maybe Spring does something similar?
我希望我更好地了解 Spring MVC,但是对于像 Jersey 和 RESTeasy 这样的 Jax-RS 实现,可以注册提供者。也许 Spring 做了类似的事情?

