【问题标题】:Spring MVC and Jackson mapping do not return the root element in jsonSpring MVC 和 Jackson 映射不返回 json 中的根元素
【发布时间】:2012-03-01 13:35:40
【问题描述】:

我在 Spring MVC 及其 json 支持方面遇到了一个问题。我进行了一次 ajax 调用以获取一些数据,并且我想以 json 格式获取该数据,包括根值。我还在实体中使用JABX 注释,因为这些注释用于某些REST API

我已经读到要获取Jackson 包含的根值,我应该使用这种方法:

this.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true);

所以我创建了一个 objectMapper,它扩展了 codehaus 一个,看起来像这样:

public class JaxbJacksonObjectMapper extends ObjectMapper {

    public JaxbJacksonObjectMapper() {
        final AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();

        this.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true);
        super.getDeserializationConfig().withAnnotationIntrospector(introspector);

        this.configure(org.codehaus.jackson.map.SerializationConfig.Feature.WRAP_ROOT_VALUE, true);
        super.getSerializationConfig().withAnnotationIntrospector(introspector);
    }
}

为了让 Spring 使用这个映射器,我配置了以下几行:

<beans:bean id="customObjectMapper" class="com.test.package.config.JaxbJacksonObjectMapper" />

<beans:bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
    <beans:property name="objectMapper" ref="customObjectMapper" />
</beans:bean>

<beans:bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <beans:property name="messageConverters">
        <beans:list>
            <beans:ref bean="jsonMessageConverter"/>
        </beans:list>
    </beans:property>
</beans:bean>

我的实体看起来像这样:

@XmlRootElement(name = "collection")
public class Issuers {
    private List<Issuer> issuers;
}

问题是当Spring 3.1 将Issuers json 对象返回给浏览器时,它不包含collection 根元素。

知道如何解决这个问题吗?

谢谢!

【问题讨论】:

标签: java spring-mvc jackson


【解决方案1】:

好像withAnnotiationIntrospector这个方法没有设置AnnotiationIntrospector。它返回new DeserializationConfig/SerializationConfig 对象(正确的AnnotiationIntrospector)。

所以,我的JaxbJacksonObjectMapper

public class JaxbJacksonObjectMapper extends ObjectMapper {

    public JaxbJacksonObjectMapper() {
        super();

        final AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();

        this.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true);
        this.configure(org.codehaus.jackson.map.SerializationConfig.Feature.WRAP_ROOT_VALUE, true);

        this.setDeserializationConfig(this.getDeserializationConfig().withAnnotationIntrospector(introspector));
        this.setSerializationConfig(this.getSerializationConfig().withAnnotationIntrospector(introspector));

    }
}

现在支持@XmlRootElement@XmlTransient等。

【讨论】:

    【解决方案2】:

    将您的“发行人”包装在通用持有人对象中。这就是我与 Jackson 和 Spring 合作时所做的。

    class JSONResponse {
    
        private Object collection;
    
        public JSONResponse(Object collection) {
            this.collection = collection;
        }
        public Object getCollection() {
            return collection;
        }
    }
    

    ...

    @RequestMappin(...)
    @ResponseBody
    public Object someHandler(...) {
        ...
        return new JSONResponse(issuers);
    }
    

    【讨论】:

    • 这可能是一种选择,谢谢。但我想获得一个更清洁的解决方案,这样我就不需要在每个请求中都更改它。但在最坏的情况下......
    • 看来spring配置不对。这并没有覆盖消息转换器,因此它没有采用我编写的 Mapper。要覆盖这些,正确的弹簧配置是:` `
    • 现在我得到了根元素,但它不是采用 jabx 注释中给出的名称,而是类的名称。知道如何解决这个问题吗?这一定与我创建的杰克逊映射器中的一些问题有关......
    【解决方案3】:

    看来弹簧配置不对。这并没有覆盖消息转换器,因此它没有采用我编写的映射器。

    要覆盖这些,正确的弹簧配置是:

        <annotation-driven>
        <message-converters>
            <beans:bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                <beans:property name="objectMapper"  ref="customObjectMapper" />
            </beans:bean>
        </message-converters>
    </annotation-driven>
    

    现在我正在获取根元素,但它不是采用 jabx 注释中给出的名称,而是类的名称。

    似乎新方法(withAnnotiationIntrospector)不能正常工作,或者我遗漏了一些东西。但如果使用已弃用的,我会得到 JABX 标签中定义的正确根名称。

        public JaxbJacksonObjectMapper() {
        final AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();
    
        this.configure(org.codehaus.jackson.map.SerializationConfig.Feature.WRAP_ROOT_VALUE, true);
        this.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true);
    
        // When using the non deprecated method (withAnnotationIntrospector),
        // there are problems with JAXB/JSON parser so don't use right now
    
        super.getDeserializationConfig().setAnnotationIntrospector(introspector);
        super.getSerializationConfig().setAnnotationIntrospector(introspector);
    }
    

    【讨论】:

      【解决方案4】:

      以下一个语句的替代用法:

      setAnnotationIntrospector(introspector);
      

      而不是遵循两个语句,

      super.getDeserializationConfig().setAnnotationIntrospector(introspector);
      super.getSerializationConfig().setAnnotationIntrospector(introspector);
      

      【讨论】:

        猜你喜欢
        • 2017-11-21
        • 1970-01-01
        • 1970-01-01
        • 2015-03-29
        • 1970-01-01
        • 1970-01-01
        • 2018-10-02
        • 2012-08-25
        • 2018-03-22
        相关资源
        最近更新 更多