我有一个来自服务器的特定 json 响应,其中在一个键下,内容将是不同的模型,而且一次只有一个模型数据会出现在该键下。
在将响应解析为 POJO 时,如何根据同一模型上的其他 contentType 字段在运行时指定对象类型。
以下是更好地理解场景的代码。
这里 content_type 是类型 A,所以在"content"关键下会有类型 TypeA 的对象的模型
"scheduled_content": {
"some_field": "value",
"content_type": "typeA",
"content" : {
"some_field" : "value"
"more_feilds" : "value"
}
}
Run Code Online (Sandbox Code Playgroud)
这里的 content_type 是类型 B,所以在"content"key下会有类 TypeB 的对象的模型
"scheduled_content": {
"some_field": "value",
"content_type": "typeB",
"content" : {
"some_field_b" : "value"
"more_fields_for_b" : "value"
}
}
Run Code Online (Sandbox Code Playgroud)
如何编写 POJO 类来解析此类 json 响应?类型类是完全不同的模型,它们没有任何共同的字段。
我相信您正在寻找的东西在 Jackson JSON 术语中被称为按属性名称进行的多态反序列化。
这是我使用 Jackson 2.1.4 的方法:
首先创建一个ScheduledContent具有公共成员的抽象类和一个对内容进行操作的抽象方法。使用JsonTypeInfo注解标记将解析特定实现的 JSON 属性,并使用注解标记JsonSubTypes通过先前指定的属性值注册子类型:
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "content_type")
@JsonSubTypes({
@JsonSubTypes.Type(name = "typeA", value = ScheduledAContent.class),
@JsonSubTypes.Type(name = "typeB", value = ScheduledBContent.class)
})
public abstract class ScheduledContent {
private String someField;
@JsonSetter("some_field")
public void setSomeField(String someField) {
this.someField = someField;
}
public abstract void doSomethingWithContent();
}
Run Code Online (Sandbox Code Playgroud)
子类型注册也可以在 上完成ObjectMapper,您将在后面看到。
然后添加类的具体实现ScheduledAContent:
public class ScheduledAContent extends ScheduledContent {
private TypeAContent content;
public void setContent(TypeAContent content) {
this.content = content;
}
@Override
public void doSomethingWithContent() {
System.out.println("someField: " + content.getSomeField());
System.out.println("anotherField: " + content.getAnotherField());
}
}
Run Code Online (Sandbox Code Playgroud)
与TypeAContent:
import com.fasterxml.jackson.annotation.JsonSetter;
public class TypeAContent {
private String someField;
private String anotherField;
@JsonSetter("some_field")
public void setSomeField(String someField) {
this.someField = someField;
}
public String getSomeField() {
return someField;
}
@JsonSetter("another_field")
public void setAnotherField(String anotherField) {
this.anotherField = anotherField;
}
public String getAnotherField() {
return anotherField;
}
}
Run Code Online (Sandbox Code Playgroud)
以及ScheduledBContent班级:
public class ScheduledBContent extends ScheduledContent {
private TypeBContent content;
public void setContent(TypeBContent content) {
this.content = content;
}
@Override
public void doSomethingWithContent() {
System.out.println("someField: " + content.getSomeField());
System.out.println("anotherField: " + content.getAnotherField());
}
}
Run Code Online (Sandbox Code Playgroud)
与TypeBContent:
import com.fasterxml.jackson.annotation.JsonSetter;
public class TypeBContent {
private String someField;
private String anotherField;
@JsonSetter("some_field_b")
public void setSomeField(String someField) {
this.someField = someField;
}
public String getSomeField() {
return someField;
}
@JsonSetter("another_field_b")
public void setAnotherField(String anotherField) {
this.anotherField = anotherField;
}
public String getAnotherField() {
return anotherField;
}
}
Run Code Online (Sandbox Code Playgroud)
和一个简单的测试类:
import java.io.IOException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.NamedType;
public class Test {
public static void main(String[] args) {
String jsonA = "{" +
"\"some_field\": \"main_some_field1\"," +
"\"content_type\": \"typeA\"," +
"\"content\" : {" +
" \"some_field\" : \"content_some_field\"," +
" \"another_field\" : \"content_another_field\"" +
"}}";
String jsonB = "{" +
"\"some_field\": \"main_some_field2\"," +
"\"content_type\": \"typeB\"," +
"\"content\" : {" +
" \"some_field_b\" : \"content_some_field_b\"," +
" \"another_field_b\" : \"content_another_field_b\"" +
"}}";
ObjectMapper mapper = new ObjectMapper();
/*
* This is another way to register the subTypes if you want to do it dynamically without the use of the
* JsonSubTypes annotation in the ScheduledContent class
*/
// mapper.registerSubtypes(new NamedType(ScheduledAContent.class, "typeA"));
// mapper.registerSubtypes(new NamedType(ScheduledBContent.class, "typeB"));
try {
ScheduledContent scheduledAContent = mapper.readValue(jsonA, ScheduledContent.class);
scheduledAContent.doSomethingWithContent();
ScheduledContent scheduledBContent = mapper.readValue(jsonB, ScheduledContent.class);
scheduledBContent.doSomethingWithContent();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这将产生输出:
someField: content_some_field
anotherField: content_another_field
someField: content_some_field_b
anotherField: content_another_field_b
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1859 次 |
| 最近记录: |