使用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();
}
答案 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 {}
答案 3 :(得分:0)
对象映射器bean可以启用默认键入:
ObjectMapper mapper = new ObjectMapper()
mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
这将给出json输出,如下所示:
[
"java.util.ArrayList",
[
{
"@class": "com.xyz.Product",
"name": "myName"
}
]
]