gpt4 book ai didi

java - 使用 Jackson 使用父节点的类型信息对 JSON 进行多态反序列化

转载 作者:行者123 更新时间:2023-12-02 10:40:22 25 4
gpt4 key购买 nike

我有这个 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;
}

我尝试在 Power 接口(interface)之上实现自定义 Jackson 反序列化器 @JsonDeserialize(using = MyStdDeserializer.class" ,但无法找到如何访问邻居节点具有类型标志的父级。

您知道如何修复类层次结构和/或使用 Jackson 功能/注释将 "first_type" 类型的 JSON 反序列化到 FirstPower 类和 "second_type “SecondPower

我使用的是 jackson 2.9.7可以稍微更改类层次结构和 JSON 格式,而且我还可以使用基于注释的反序列化。

最佳答案

type信息存储在 Dto类、定制JsonDeserializer应该为“Dto”类而不是“Power”接口(interface)实现,以便访问type信息。实现定制的关键一环JsonDeserializer下面的代码是行

config.powers.add(parser.readValueAs(getPowerClass(dto.type)));

哪里getPowerClass方法通过使用 FirstPower 确定所需的类( SecondPowertype )的dto 。一旦知道了类,我们就可以反序列化 power只需调用 readValueAs 即可对象方法。以下类(应放在同一个包中)演示了如何实现自定义 JsonDeserializer

主类

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 "
+ " } "
+ " } "
+ " ] "
+ " } ";

}
}

D 类

import java.util.Collection;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

@JsonDeserialize(using = DtoDeserializer.class)
public class Dto {
String type;
Collection<Config> configs;
}

DtoDeserializer 类

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);
}
}

电源接口(interface)

public interface Power {}

FirstPower 类

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;
}
}

二次幂级

public class SecondPower implements Power {
boolean anotherParam;

boolean isAnotherParam() {
return anotherParam;
}

void setAnotherParam(boolean anotherParam) {
this.anotherParam = anotherParam;
}

@Override
public String toString() {
return "anotherParam:" + String.valueOf(anotherParam);
}
}

关于java - 使用 Jackson 使用父节点的类型信息对 JSON 进行多态反序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52959192/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com