Joh*_*aum 10 java serialization json jackson
假设我有以下格式的JSON:
{
"type" : "Foo"
"data" : {
"object" : {
"id" : "1"
"fizz" : "bizz"
...
},
"metadata" : {
...
},
"owner" : {
"name" : "John"
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
我试图避免自定义反序列化器并尝试将上述JSON(称为Wrapper.java)反序列化为Java POJO."类型"字段指示"对象"反序列化即.type = foo表示使用Foo.java反序列化"object"字段.(如果type = Bar,请使用Bar.java反序列化对象字段).元数据/所有者将始终使用简单的Jackson注释Java类以相同的方式反序列化.有没有办法使用注释来完成这个?如果没有,如何使用自定义解串器完成?
cas*_*lin 16
或者在自定义解串器的方式,你可以有一个注释,唯一的解决办法如下(类似于中描述的Spunc的答案,但使用type作为外部属性):
public abstract class AbstractData {
private Owner owner;
private Metadata metadata;
// Getters and setters
}
Run Code Online (Sandbox Code Playgroud)
public static final class FooData extends AbstractData {
private Foo object;
// Getters and setters
}
Run Code Online (Sandbox Code Playgroud)
public static final class BarData extends AbstractData {
private Bar object;
// Getters and setters
}
Run Code Online (Sandbox Code Playgroud)
public class Wrapper {
private String type;
@JsonTypeInfo(use = Id.NAME, property = "type", include = As.EXTERNAL_PROPERTY)
@JsonSubTypes(value = {
@JsonSubTypes.Type(value = FooData.class, name = "Foo"),
@JsonSubTypes.Type(value = BarData.class, name = "Bar")
})
private AbstractData data;
// Getters and setters
}
Run Code Online (Sandbox Code Playgroud)
在此方法中,@JsonTypeInfo设置为type用作外部属性来确定映射data属性的正确类.
JSON文档可以反序列化如下:
ObjectMapper mapper = new ObjectMapper();
Wrapper wrapper = mapper.readValue(json, Wrapper.class);
Run Code Online (Sandbox Code Playgroud)
您可以使用自定义反序列化程序检查type属性以将object属性解析为最合适的类.
首先定义一个将由Foo和Bar类实现的接口:
public interface Model {
}
Run Code Online (Sandbox Code Playgroud)
public class Foo implements Model {
// Fields, getters and setters
}
Run Code Online (Sandbox Code Playgroud)
public class Bar implements Model {
// Fields, getters and setters
}
Run Code Online (Sandbox Code Playgroud)
然后定义你的Wrapper和Data类:
public class Wrapper {
private String type;
private Data data;
// Getters and setters
}
Run Code Online (Sandbox Code Playgroud)
public class Data {
@JsonDeserialize(using = ModelDeserializer.class)
private Model object;
private Metadata metadata;
private Owner owner;
// Getters and setters
}
Run Code Online (Sandbox Code Playgroud)
该object字段用注释@JsonDeserialize,表示将用于该object属性的反序列化器.
解串器定义如下:
public class ModelDeserializer extends JsonDeserializer<Model> {
@Override
public Model deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonMappingException {
// Get reference to ObjectCodec
ObjectCodec codec = jp.getCodec();
// Parse "object" node into Jackson's tree model
JsonNode node = codec.readTree(jp);
// Get value of the "type" property
String type = ((Wrapper) jp.getParsingContext().getParent()
.getCurrentValue()).getType();
// Check the "type" property and map "object" to the suitable class
switch (type) {
case "Foo":
return codec.treeToValue(node, Foo.class);
case "Bar":
return codec.treeToValue(node, Bar.class);
default:
throw new JsonMappingException(jp,
"Invalid value for the \"type\" property");
}
}
}
Run Code Online (Sandbox Code Playgroud)
JSON文档可以反序列化如下:
ObjectMapper mapper = new ObjectMapper();
Wrapper wrapper = mapper.readValue(json, Wrapper.class);
Run Code Online (Sandbox Code Playgroud)
所有这些都可以通过注释来完成.
使用"元数据"和"所有者"等公共字段及其getter/setter创建一个抽象超类.该类需要使用@JsonTypeInfo进行注释.它应该看起来像:
@JsonTypeInfo(use = Id.CLASS, include = As.PROPERTY, property = "type")
Run Code Online (Sandbox Code Playgroud)
使用参数property = "type"指定类标识符将在JSON文档中的字段类型下序列化.
可以使用指定类标识符的值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")
})
Run Code Online (Sandbox Code Playgroud)
通过从抽象超类扩展来实现您的类Foo和Bar.
Jackson的ObjectMapper将使用JSON文档的附加字段"type"进行序列化和反序列化.E. g.当您将JSON字符串反序列化为超类引用时,它将是适当的子类:
ObjectMapper om = new ObjectMapper();
AbstractBase x = om.readValue(json, AbstractBase.class);
// x will be instanceof Foo or Bar
Run Code Online (Sandbox Code Playgroud)
完整的代码示例(我使用公共字段作为快捷方式,不需要编写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 + ']';
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15652 次 |
| 最近记录: |