@JsonTypeInfo可以与集合一起使用吗?

时间:2011-09-19 15:42:50

标签: json spring serialization spring-mvc jackson

使用Spring 3和Jackson 1.7.6,我可以序列化抽象类的实现,并将类的完全限定名称输出为名为@class的属性。当我的Spring控制器从带有@ResponseBody注释的控制器返回单个实例时,这很好。

当返回上述类型的Collection时,生成的JSON会根据序列化的类型(每个子类的字段都存在)而发生更改,但它不包含@class属性,客户代码需要。

如何在返回集合时将此类型提示添加到序列化的JSON中?

//Returns complete with @class=com.package.blah
@RequestMapping("/json/getProduct.json")
public @ResponseBody Product getProduct(Integer id)
{
    return service.getProduct(id);
}

//Does not include @class 
@RequestMapping("/json/getProducts.json")
public @ResponseBody List<Product> getProducts()
{
    return service.getProducts();
}

4 个答案:

答案 0 :(得分:2)

为此,您需要配置ObjectMapper。这通过Spring并不简单,因为ObjectMapper具有可设置其状态的可调用方法(而不是可设置的属性),然后将其存储为位掩码。

如果您使用的是<mvc:annotation-driven />,则需要将其替换为等效标记,该标记可以在Spring JavaDocs中找到。

扩展ObjectMapper:

public class ConfigurableObjectMapper extends ObjectMapper
{
    public ConfigurableObjectMapper()
    {
        this.enableDefaultTypingAsProperty(DefaultTyping.JAVA_LANG_OBJECT, JsonTypeInfo.Id.CLASS.getDefaultPropertyName());
    }
}

然后告诉Spring使用此类的实例而不是默认实现。

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="order" value="0" />
</bean>

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="webBindingInitializer">
        <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
            <property name="validator" ref="validator" />
        </bean>
    </property>
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                <property name="objectMapper">
                    <bean class="com.blitzgamesstudios.web.common.json.ConfigurableObjectMapper" />
                </property>
            </bean>
            <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
            <bean class="org.springframework.http.converter.FormHttpMessageConverter" />
            <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
        </list>
    </property>
</bean>

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

答案 1 :(得分:2)

您可以将@JsonTypeInfo与POJO,集合和映射一起使用,但请注意,集合和映射的声明值类型必须是具有(或继承)@JsonTypeInfo批注的值(使用每类@JsonTypeInfo批注时)。这不起作用,例如,如果你有类似“收集”的类型 - 在这种情况下,Deejay的答案是正确的,因为你可以强制包含“默认输入”选项。

但是如果你有一个Collection属性来序列化/反序列化,那么事情也应该有效,即:

public class Bean {
    @JsonTypeInfo(....)
    public Collection<Object> listOfObjects; // does work because it's per-property annotation!
    // ... also, applies to value type and not Collection type itself
}

因为那将覆盖任何@JsonTypeInfo注释值类型否则可能

答案 2 :(得分:0)

我遇到了java.util.Map的问题,所以我做了类似的事情:

public interface MyMap extends Map<Long, Product> {}

public class MyHashMap extends HashMap<Long, Product> implements MyMap {}

发现于:http://jackson-users.ning.com/forum/topics/mapper-not-include-type-information-when-serializing-object-why

答案 3 :(得分:0)

对象映射器bean可以启用默认键入:

ObjectMapper mapper = new ObjectMapper() mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);

这将给出json输出,如下所示:

[
    "java.util.ArrayList",
    [
        {
            "@class": "com.xyz.Product",
            "name": "myName"
        }
     ]
]