简体   繁体   English

杰克逊弹簧控制器序列化

[英]jackson spring controller serialization

I have a Java Spring 3.2 + Hibernate project. 我有一个Java Spring 3.2 + Hibernate项目。

I used jackson2 annotations (com.fasterxml.jackson.annotation) in the model, and I (guess) the spring rest controller should use jackson2 (aka com.fasterxml.jackson) when serializing the requested objects. 我在模型中使用了jackson2批注(com.fasterxml.jackson.annotation),并且在序列化请求的对象时(猜测)弹簧支架控制器应使用jackson2(又名com.fasterxml.jackson)。

I configured the application with: 我为应用程序配置了:

        <!-- Use the HibernateAware mapper instead of the default -->
        <bean
            class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="myProj.util.HibernateAwareObjectMapper">
                    <property name="serializationInclusion">
                        <value type="com.fasterxml.jackson.annotation.JsonInclude.Include">NON_NULL</value>
                    </property>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>

The HibernateAwareObjectMapper is defined this way: HibernateAwareObjectMapper是这样定义的:

package myProj.util;

import com.fasterxml.jackson.databind.ObjectMapper;

public class HibernateAwareObjectMapper extends ObjectMapper {
private static final long serialVersionUID = -5002954669679467811L;

public HibernateAwareObjectMapper() {
        Hibernate4Module hbm = new Hibernate4Module();
        hbm.enable(Hibernate4Module.Feature.FORCE_LAZY_LOADING);
        registerModule(hbm);
    }
}

so I can state that it extends the com.fasterxml ObjectMapper (OTOH I'm not sure why it was added, since I just inherited the code from other developers). 因此我可以声明它扩展了com.fasterxml ObjectMapper (我不确定为什么要添加它,因为我只是从其他开发人员那里继承了代码)。

Note that from what I know spring3.2 should use jackson2 by default. 请注意,据我所知,默认情况下spring3.2应该使用jackson2。 This is mostly working fine but then I have a serialization issue which only happens with a specific service/controller. 这在大多数情况下都可以正常工作,但是我遇到了序列化问题,仅在特定的服务/控制器中会发生。 I have an object which defines a parent, containing the same object as a child. 我有一个定义父对象的对象,其中包含与子对象相同的对象。 This is resulting in a serialization loop, which ends with an exception on the server side: 这导致序列化循环,最后在服务器端出现异常:

[...]
        at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
        at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446)
        at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
        at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446)
        at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150)
        at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
        at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446)
        at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150)
[...]

and an incomplete JSON sent to the client. 以及发送给客户端的不完整的JSON。

This is the controller code: 这是控制器代码:

@RequestMapping(value = "/getReleases", method = RequestMethod.POST)
public Map<String, Object> getReleases(@RequestBody Project project) {
    Map<String, Object> subProjectsMap = new HashMap<String, Object>();
    List<Release> releaseList = null;
    try {
        releaseList = jiraService.getReleases(project);
        subProjectsMap.put("success", (releaseList.size() > 0) ? true : false);
        subProjectsMap.put("data", releaseList);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return subProjectsMap;
}

Serialization is performed implicitly by the framework. 序列化由框架隐式执行。

The question is: why is spring apparently using org.codehaus.jackson rather than com.fasterxml.jackson as I would expect? 问题是:为什么Spring显然使用org.codehaus.jackson而不是我期望的com.fasterxml.jackson? Note that the model describing the serialized object is using jackson2 annotations (in particular @JsonBackReference and @JsonIgnore), so they are possibly ignored when using jackson1, which (I think) may result in the loop issue. 请注意,描述序列化对象的模型使用的是jackson2批注(特别是@JsonBackReference和@JsonIgnore),因此在使用jackson1时可能会忽略它们,(我认为)这可能会导致循环问题。

After many hours spent banging my head I still don't know why this is happening. 经过数小时的敲打我的头,我仍然不知道为什么会这样。 Can you provide any hint? 你能提供任何提示吗?

Well, it turned out the problem was due to the missing @ResponseBody annotation in the controller code. 恩,事实证明问题出在控制器代码中,因为缺少@ResponseBody批注。

 @RequestMapping(value = "/getReleases", method = RequestMethod.POST)
 public @ResponseBody Map<String, Object> getReleases(@RequestBody Project project) {
      [...]
 }

Adding the @ResponseBody annotation magically fixed the problem for me. 添加@ResponseBody批注为我神奇地解决了该问题。

I realized the problem by comparing this controller code with the code from similar controllers which were not showing the issue (silly of me not doing this before), after several vain attempts at digging through the Spring code. 在几次徒劳的挖掘Spring代码的尝试之后,我通过将该控制器代码与未显示问题的类似控制器的代码进行比较来实现这个问题(傻瓜我以前没有这样做)。

Thanks all for the answers! 谢谢大家的回答!

Spring automatically configures MappingJackson2HttpMessageConverter when Jackson2 is on the classpath. Jackson2在类路径上时,Spring会自动配置MappingJackson2HttpMessageConverter However, you override this behavior by defining your own bean of type MappingJackson2HttpMessageConverter . 但是,您通过定义自己的MappingJackson2HttpMessageConverter类型的bean来覆盖此行为。 First of all, check if it is your bean being used for serialization (eg via debugging). 首先,检查它是否用于序列化(例如,通过调试)您的bean。 Then check its configuration. 然后检查其配置。 It seems the constructor of the Hibernate extension to ObjectMapper is not calling super() , which means that configuration of the default SerializerProvider and BeanSerializerFactory is missing. 看来ObjectMapper的Hibernate扩展的构造函数没有调用super() ,这意味着缺少默认的SerializerProviderBeanSerializerFactory配置。 See http://fasterxml.github.io/jackson-databind/javadoc/2.0.0/com/fasterxml/jackson/databind/ObjectMapper.html for more details. 有关更多详细信息,请参见http://fasterxml.github.io/jackson-databind/javadoc/2.0.0/com/fasterxml/jackson/databind/ObjectMapper.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM