我想反序列化一个可以具有“未知”属性(但在编译时已知泛型)的 json 字符串,并将该未知属性反序列化为提供的泛型类型。
JSON 字符串的结构如下所示:
{
"id":"abc",
"human": {"name": "me", age: 99}
}
OR:
{
"id":"abc",
"cat": {"color": "orange"}
}
OR:
{
"id":"abc",
"bike": {"specs": {"speed":30}}
}
我有以下模型类:
@Value
@Builder
@Jacksonized
public class Data<T> {
String id;
T other; // <- how can I map "cat", "human", or "bike" into this generic
}
@V/B/J
public class Human {
String name;
Integer age;
}
@V/B/J
public class Cat {
String color;
}
@V/B/J
public class Bike {
Specs specs;
}
@V/B/J
public class Specs {
Integer speed;
}
JSON 字符串所需的泛型将在编译时已知,例如:
Data<Human> humanData = objectMapper.readValue(jsonHumanString, TypeReference<Data<Human>>() {});
Data<Cat> catData = objectMapper.readValue(jsonCatString, TypeReference<Data<Cat>>() {});
Data<Bike> bikeData = objectMapper.readValue(jsonBikeString, TypeReference<Data<Bike>>() {});
但是,我仍然收到错误:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "human"
。如何将“自行车”、“猫”、“人”强行映射为“其他”?
我想我解决了自己的答案。我可以在整个
Data
类上使用自定义反序列化器来解析泛型。
@Value
@Builder
@JsonDeserialize(using = GenericDeserializer.class)
public class Data<T> {
String id;
T other;
}
解串器:
public class GenericDeserializer extends StdDeserializer<Data<?>> {
public GenericDeserializer() {
this(null);
}
public GenericDeserializer(Class<Data<?>> vc) {
super(vc);
}
@Override
public Data<?> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException, JsonProcessingException {
ObjectCodec codec = jsonParser.getCodec();
JsonNode node = codec.readTree(jsonParser);
if (node.has("bike")) {
return Data.<Bike>builder()
.id(String.valueOf(node.get("id")))
.other(codec.treeToValue(node.get("bike"), Bike.class))
.build();
} else if (node.has("human)) {
return Data.<Human>builder()
.id(String.valueOf(node.get("id")))
.other(codec.treeToValue(node.get("human"), Human.class))
.build();
} else if (node.has("cat)) {
return Data.<Cat>builder()
.id(String.valueOf(node.get("id")))
.other(codec.treeToValue(node.get("cat"), Cat.class))
.build();
}
}
}