目的: Json序列化/反序列化不需要知道具体子类的类型,只需要根据父类以及类别标识就能准确判断子类类型。
方式一:全局Default Typing机制
1 2 |
|
方式二: 为Class添加@JsonTypeInfo
方式一是全局的方式,会导致序列化后的json结构改变,比如原来的{"prop":"val"}会变成["@class":"class类型",{"prop":"val"}]
而方式二仅在类里新加一个属性,不会破坏json的结构,因此这里采用方式二。
大多数文献都是采用直接在类里写注解的方式,比如:
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
class Animal { }
这里采用在jaxb xsd中加注解的方式实现。
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://bill.com/data" xmlns="http://bill.com/data"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.1"
xmlns:annox="http://annox.dev.java.net"
xmlns:ja="http://annox.dev.java.net/org.codehaus.jackson.annotate"
jaxb:extensionBindingPrefixes="annox">
<xsd:complexType name="BaseClass" abstract="true">
<xsd:annotation>
<xsd:appinfo>
<annox:annotate>
<ja:JsonTypeInfo use="CLASS" include="PROPERTY" property="@class"/>
</annox:annotate>
</xsd:appinfo>
</xsd:annotation>
</xsd:complexType>
<xsd:complexType name="SubClass">
<xsd:complexContent>
<xsd:extension base="BaseClass">
<xsd:sequence>
<xsd:element name="prop1" type="xsd:string" />
<xsd:element name="prop2" type="xsd:string" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
生成的java类如下:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BaseClass")
@XmlSeeAlso({
SubClass.class
})
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class", include = JsonTypeInfo.As.PROPERTY)
public abstract class BaseClass
implements Serializable
{
private final static long serialVersionUID = 1L;
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "SubClass", propOrder = {
"prop1",
"prop2"
})
public class SubClass
extends BaseClass
implements Serializable
{
private final static long serialVersionUID = 1L;
@XmlElement(required = true)
protected String prop1;
@XmlElement(required = true)
protected String prop2;
/**
* 获取prop1属性的值。
*
* @return
* possible object is
* {@link String }
*
*/
public String getProp1() {
return prop1;
}
/**
* 设置prop1属性的值。
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setProp1(String value) {
this.prop1 = value;
}
/**
* 获取prop2属性的值。
*
* @return
* possible object is
* {@link String }
*
*/
public String getProp2() {
return prop2;
}
/**
* 设置prop2属性的值。
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setProp2(String value) {
this.prop2 = value;
}
pom.xml中的关键配置:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.2</version>
</dependency>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<args>
<arg>-Xannotate</arg>
</args>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics-annotate</artifactId>
<version>0.6.3</version>
</plugin>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics</artifactId>
<version>0.6.3</version>
</plugin>
</plugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.2</version>
</dependency>
</dependencies>
</plugin>
</plugins>
然后构造一个Jackson的工具类:
public class JacksonUtil {
public static String bean2Json(Object obj) {
ObjectMapper mapper = new ObjectMapper();
// mapper.enableDefaultTyping();
// mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
try {
return mapper.writeValueAsString(obj);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static <T> T json2Bean(String json, Class<T> klass) {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.readValue(json, klass);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
测试代码:
SubClass sub1 = new SubClass();
sub1.setProp1("testing");
BaseClass base = sub1;
String json = JacksonUtil.bean2Json(base);
System.out.println("serialize: " + json);
BaseClass base2 = JacksonUtil.json2Bean(json, BaseClass.class);
SubClass sub2 = (SubClass) base2;
System.out.println("deserialize: " + sub2.getProp1());
输出结果如下:
22:36:52,974 INFO [stdout] (http--0.0.0.0-8080-11) serialize: {"@class":"com.bill.data.SubClass","prop1":"testing","prop2":null}
22:36:52,979 INFO [stdout] (http--0.0.0.0-8080-11) deserialize: testing
参考文献:
http://codelife.me/blog/2012/11/03/jackson-polymorphic-deserialization/