我有这个JSON文档
1:
{
"type": "first_type",
"configs": [
{
"itemLevel": 1,
"power": {
"firstTypeParam": "xxxx"
}
},
{
"itemLevel": 2,
"power": {
"firstTypeParam": "yyy"
}
}
]
}
2:
{
"type": "second_type",
"configs": [
{
"itemLevel": 11,
"power": {
"anotherParam": true
}
},
{
"itemLevel": 12,
"power": {
"anotherParam": false
}
]
}
几个Java类
public class Dto {
String type;
Collection<Config>;
}
public class Config {
int itemLevel;
Collection<Power> powers;
}
public interface Power {}
public class FirstPower implements Power {
String firstTypeParam;
}
public class SecondPower implements Power {
boolean anotherParam;
}
我尝试在@JsonDeserialize(using = MyStdDeserializer.class"
界面的顶部实现自定义杰克逊解串器Power
,但是找不到如何访问带有类型标志的父节点的邻居节点。
您是否知道如何修复类层次结构和/或使用杰克逊功能/注释将"first_type"
类型的FirstPower
类型和"second_type"
类型的SecondPower
反序列化JSON?< / p>
我正在使用杰克逊2.9.7 可以稍微更改类层次结构和JSON格式,而且我也可以使用基于注释的反序列化。
答案 0 :(得分:1)
由于type
信息存储在Dto
类中,因此应为'Dto'类而不是'Power'接口实现自定义JsonDeserializer
,以便访问{{1 }}信息。以下代码中实现自定义type
的关键部分是
config.powers.add(parser.readValueAs(getPowerClass(dto.type)));
其中JsonDeserializer
方法使用getPowerClass
中的FirstPower
确定所需的类(SecondPower
或type
)。一旦知道了该类,就可以简单地通过调用dto
方法来反序列化power
对象。以下类(应放在同一包中)演示了如何实现自定义readValueAs
。
主班
JsonDeserializer
Dto类
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class PolymorphicDeserialize {
public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
Dto type1 = mapper.readValue(getType1Json(), Dto.class);
Dto type2 = mapper.readValue(getType2Json(), Dto.class);
printDto(type1);
printDto(type2);
}
private static void printDto(Dto dto) {
System.out.println("type :" + dto.type);
for (Config config : dto.configs) {
System.out.println("itemLevel:" + config.itemLevel);
System.out.println("powers:" + config.powers);
}
}
private static String getType1Json() {
return " { "
+ " \"type\": \"first_type\", "
+ " \"configs\": [ "
+ " { "
+ " \"itemLevel\": 1, "
+ " \"power\": { "
+ " \"firstTypeParam\": \"xxxx\" "
+ " } "
+ " }, "
+ " { "
+ " \"itemLevel\": 2, "
+ " \"power\": { "
+ " \"firstTypeParam\": \"yyy\" "
+ " } "
+ " } "
+ " ] "
+ " } ";
}
private static String getType2Json() {
return " { "
+ " \"type\": \"second_type\", "
+ " \"configs\": [ "
+ " { "
+ " \"itemLevel\": 11, "
+ " \"power\": { "
+ " \"anotherParam\": true "
+ " } "
+ " }, "
+ " { "
+ " \"itemLevel\": 12, "
+ " \"power\": { "
+ " \"anotherParam\": false "
+ " } "
+ " } "
+ " ] "
+ " } ";
}
}
DtoDeserializer类
import java.util.Collection;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
@JsonDeserialize(using = DtoDeserializer.class)
public class Dto {
String type;
Collection<Config> configs;
}
电源接口
import java.io.IOException;
import java.util.ArrayList;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
public class DtoDeserializer extends JsonDeserializer<Dto> {
@Override
public Dto deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
Dto dto = new Dto();
dto.configs = new ArrayList<Config>();
while (parser.nextToken() == JsonToken.FIELD_NAME) {
deserializeType(parser, dto);
deserializeConfigs(parser, dto);
}
return dto;
}
private void deserializeType(JsonParser parser, Dto dto) throws IOException, JsonProcessingException {
if (!"type".equals(parser.getCurrentName())) {
return;
}
parser.nextToken();
dto.type = parser.getValueAsString();
}
private void deserializeConfigs(JsonParser parser, Dto dto) throws IOException, JsonProcessingException {
if (!"configs".equals(parser.getCurrentName())) {
return;
}
if (parser.nextToken() != JsonToken.START_ARRAY) {
return;
}
while (parser.nextValue() != null) {
if (parser.getCurrentToken() != JsonToken.START_OBJECT) {
continue;
}
Config config = new Config();
config.powers = new ArrayList<Power>();
while (parser.nextToken() != JsonToken.END_OBJECT) {
if ("itemLevel".equals(parser.getCurrentName())) {
parser.nextToken();
config.itemLevel = parser.getValueAsInt();
} else if ("power".equals(parser.getCurrentName())) {
parser.nextToken();
config.powers.add(parser.readValueAs(getPowerClass(dto.type)));
}
}
dto.configs.add(config);
}
}
private Class<? extends Power> getPowerClass(String type) {
if ("first_type".equals(type)) {
return FirstPower.class;
} else if ("second_type".equals(type)) {
return SecondPower.class;
}
throw new IllegalArgumentException("Not known type" + type);
}
}
FirstPower类
public interface Power {}
SecondPower类
public class FirstPower implements Power {
String firstTypeParam;
String getFirstTypeParam() {
return firstTypeParam;
}
void setFirstTypeParam(String firstTypeParam) {
this.firstTypeParam = firstTypeParam;
}
@Override
public String toString() {
return "firstTypeParam:" + firstTypeParam;
}
}