Spring MVC和Jackson映射不返回json中的根元素

时间:2012-03-01 13:35:41

标签: java spring-mvc jackson

我遇到了一个关于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将问题者json对象返回给浏览器时,它不包含collection根元素。

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

谢谢!

4 个答案:

答案 0 :(得分:3)

似乎方法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和其他。

答案 1 :(得分:0)

将您的“发行人”包裹在通用持有人对象中。这就是我在与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);
}

答案 2 :(得分:0)

看起来弹簧配置不对。这并没有覆盖messageconverters,所以它没有采用我写的Mapper。

要覆盖它们,正确的spring配置为:

    <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);
}

答案 3 :(得分:0)

在一个陈述之后替代此用法:

setAnnotationIntrospector(introspector);

而是遵循两个陈述,

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