"result" : {
"id" : "123",
"category" : "typeA",
"value" : {
"typeAField" : "123"
}
}
"result" : {
"id" : "321",
"category" : "typeB",
"value" : {
"typeBAField1" : "123",
"typeBAField2" : true
}
}
字符串
我想把这样的json结构改成java对象,结果有id、category和value,value中对象的类型根据category而变化。
所以我创建了这样的对象:当类别的值是typeA时,我想使用TypeA.java对象,当类别的值是typeB时,我想使用TypeB.java对象。
public class Result {
String id;
String category;
Values value;
}
public abstract class Values {
}
public TypeA extends Values {
String typeAField;
}
public TypeB extends Values {
String typeBField1;
String typeBField2;
}
型
输入如下:
"result" : {
"id" : "123",
"category" : "typeA",
"value" : {
"typeAField" : "123"
}
}
型
当输入文本时,我想编写代码将其转换为Result.java对象。
第一种方法
@Data
class Result {
private String id;
private String category;
private Values value;
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT, property = "category")
@JsonSubTypes({
@JsonSubTypes.Type(value = TypeA.class, name = "typeA"),
@JsonSubTypes.Type(value = TypeB.class, name = "typeB")
})
abstract class Values {}
@Data
class TypeA extends Values {
private String typeAField;
}
@Data
class TypeB extends Values {
private String typeBAField1;
private boolean typeBAField2;
}
String json1 = "{\"id\":\"123\",\"category\":\"typeA\",\"value\":{\"typeAField\":\"123\"}}";
String json2 = "{\"id\":\"321\",\"category\":\"typeB\",\"value\":{\"typeBAField1\":\"123\",\"typeBAField2\":true}}";
ObjectMapper objectMapper = new ObjectMapper();
Result result1 = objectMapper.readValue(json1, Result.class); // error
Result result2 = objectMapper.readValue(json2, Result.class);
型
错误详情
com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'typeAField' as a subtype of `Values`: known type ids = [typeA, typeB] (for POJO property 'value')
at [Source: (String)"{"id":"123","category":"typeA","value":{"typeAField":"123"}}"; line: 1, column: 41] (through reference chain: Result["value"])
型
我尝试的第二种方法
@Data
class Result {
private String id;
private String category;
private Values value;
@JsonSetter("value")
public void setValue(Map<String, Object> valueMap) {
ObjectMapper objectMapper = new ObjectMapper();
try {
if (valueMap.containsKey("typeAField")) {
this.value = objectMapper.convertValue(valueMap, TypeA.class);
}
else {
this.value = objectMapper.convertValue(valueMap, TypeB.class);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
abstract class Values {}
@Data
class TypeA extends Values {
private String typeAField;
}
@Data
class TypeB extends Values {
private String typeBAField1;
private boolean typeBAField2;
}
型
它的工作,但setter部分似乎不干净。有什么更好的方法吗?我缺乏很多,但我想得到帮助提前谢谢你
1条答案
按热度按时间ukdjmx9f1#
在第一个方法中,您使用
JsonTypeInfo.As.WRAPPER_OBJECT
,如果JSON数据是这样的,它将工作:字符串
现在,您可以使用
JsonTypeInfo.As.EXTERNAL_PROPERTY
,它只能用于属性,而不是根据JavaBean的类型(类)。public static final JsonTypeInfo.As EXTERNAL_PROPERTY
包含机制类似于PROPERTY,不同之处在于属性在层次结构中高出一级,即作为与JSON Object相同级别的兄弟属性包含到类型中。请注意,此选项只能用于属性,而不能用于类型(类)。尝试将其用于类将导致基本PROPERTY的包含策略
所以你必须使用
JsonTypeInfo.As.EXTERNAL_PROPERTY
注解Result类的value属性,并删除抽象的Values类注解。然后你就可以无错误地对JSON数据进行格式化。型