这一切都可以通过注解来完成。
使用“元数据”和“所有者”等公共字段及其 getter/setter 创建一个抽象超类。这个类需要用@JsonTypeInfo注解。它应该看起来像:
@JsonTypeInfo(use = Id.CLASS, include = As.PROPERTY, property = "type")
使用参数property = "type" 指定类标识符将在 JSON 文档中的字段 type 下序列化。
类标识符的值可以用use 指定。 Id.CLASS 使用完全限定的 Java 类名。您还可以使用Id.MINIMAL_CLASS,它是Java 类的缩写名称。要拥有自己的标识符,请使用Id.NAME。在这种情况下,您需要声明子类型:
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Foo.class, name = "Foo"),
@JsonSubTypes.Type(value = Bar.class, name = "Bar")
})
通过从抽象超类扩展来实现您的类 Foo 和 Bar。
Jackson 的 ObjectMapper 将使用 JSON 文档的附加字段“类型”进行序列化和反序列化。例如。当您将 JSON 字符串反序列化为超类引用时,它将属于适当的子类:
ObjectMapper om = new ObjectMapper();
AbstractBase x = om.readValue(json, AbstractBase.class);
// x will be instanceof Foo or Bar
完整代码示例(我使用公共字段作为快捷方式,无需编写 getter/setter):
package test;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import java.io.IOException;
import com.fasterxml.jackson.annotation.JsonSubTypes;
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Foo.class, name = "Foo"),
@JsonSubTypes.Type(value = Bar.class, name = "Bar")
})
public abstract class AbstractBase {
public MetaData metaData;
public Owner owner;
@Override
public String toString() {
return "metaData=" + metaData + "; owner=" + owner;
}
public static void main(String[] args) throws IOException {
// Common fields
Owner owner = new Owner();
owner.name = "Richard";
MetaData metaData = new MetaData();
metaData.data = "Some data";
// Foo
Foo foo = new Foo();
foo.owner = owner;
foo.metaData = metaData;
CustomObject customObject = new CustomObject();
customObject.id = 20l;
customObject.fizz = "Example";
Data data = new Data();
data.object = customObject;
foo.data = data;
System.out.println("Foo: " + foo);
// Bar
Bar bar = new Bar();
bar.owner = owner;
bar.metaData = metaData;
bar.data = "A String in Bar";
ObjectMapper om = new ObjectMapper();
// Test Foo:
String foojson = om.writeValueAsString(foo);
System.out.println(foojson);
AbstractBase fooDeserialised = om.readValue(foojson, AbstractBase.class);
System.out.println(fooDeserialised);
// Test Bar:
String barjson = om.writeValueAsString(bar);
System.out.println(barjson);
AbstractBase barDeserialised = om.readValue(barjson, AbstractBase.class);
System.out.println(barDeserialised);
}
}
class Foo extends AbstractBase {
public Data data;
@Override
public String toString() {
return "Foo[" + super.toString() + "; data=" + data + ']';
}
}
class Bar extends AbstractBase {
public String data;
public String toString() {
return "Bar[" + super.toString() + "; data=" + data + ']';
}
}
class Data {
public CustomObject object;
@Override
public String toString() {
return "Data[object=" + object + ']';
}
}
class CustomObject {
public long id;
public String fizz;
@Override
public String toString() {
return "CustomObject[id=" + id + "; fizz=" + fizz + ']';
}
}
class MetaData {
public String data;
@Override
public String toString() {
return "MetaData[data=" + data + ']';
}
}
class Owner {
public String name;
@Override
public String toString() {
return "Owner[name=" + name + ']';
}
}