Json 解析丢失子类信息

2023-07-07 08:12:58 +08:00
 nnegier

子类们的共同父类:BasePlugin

生成 Json ,子类信息都可以很好的输出

String json = new Gson().toJson(list);

但是,如果从 Json 中解析泛型类,它的子类的信息就获取不到,无法类型强转

Type type = new TypeToken<List<BasePlugin>>() {
}.getType();
return new Gson().fromJson(json, type);

这个有可能解决吗?

2477 次点击
所在节点    Java
12 条回复
chendy
2023-07-07 08:20:25 +08:00
koloonps
2023-07-07 09:08:40 +08:00
new ObjectMapper().readValue("", new TypeReference<Object>() {
@Override
public Type getType() {
return super.getType();
}
})
AoEiuV020JP
2023-07-07 10:08:47 +08:00
讲道理,仔细想想, 如果可以从父类泛型这样得到子类的属性,那人家直接内置一个,
Type type = new TypeToken<List<Object>>() {
}.getType();
压根都不需要暴露出 TypeToken 了,

这问题一定是无解的, 具体类型必须有个渠道提供给 json 框架,
加个 if else 判断然后 new 不同的 TypeToken 吧,
或者这个 type 改从外部传入,
MozzieW
2023-07-07 10:17:16 +08:00
楼上的回复解决的范型 List ,OP 要的是范型 List+子类。
实践上,应该不能这么操作。解决范型 List 反序列话时候,我们是通过带入一个 Type 指定类型,解决类型丢失问题。而 OP 场景下,还多了一个子类型丢失问题。
最简单的方法,不要用子类,一个类接收全部参数,通过 type 区分行为,后续通过设计模式、switch 、if 代码 解决代码复用、逻辑问题。
其他方法:JSON 序列化时引入子类 type ,反序列化时先转为 map ,再根据 type 的值转为子类。
xiangyuecn
2023-07-07 10:42:33 +08:00
你实例化一个父类的实例,怎么可能会包含子类才有的属性🐶
shily
2023-07-07 11:18:59 +08:00
这个问题分两种情况:
1. 列表中的元素是同一种类型的,这样只需要调整一下类型信息就行了 new TypeToken<List<PluginA>>() {}.getType(); 来获取单一类型的 list ,这样 list 中的元素就是 PluginA ;
2. 列表中的元素是混合类型的,混合了类型 PluginA 和 类型 PluginB ,这样的话,需要自己注册反系列化器 JsonDeserializer 来识别类型;

wqhui
2023-07-07 11:43:23 +08:00
反序列化的时候填了父类,解析的时候怎么知道你的子类有什么属性,或者说如果有一堆子类怎么知道装载成那个子类才是对的。
反序列化时需要想办法指定子类,比如参考 mongodb ,在序列化结果加上序列化的 class ,反序列化根据这个 class 来弄;比如在代码中使用注解标记 List 中的范型具体 class 是什么。
oneisall8955
2023-07-07 12:13:35 +08:00
fastjson 携带类信息,或许可以解决

https://blog.csdn.net/xl_1803/article/details/128375110

( csdn🐶)

但印象这个有安全性问题
Leon406
2023-07-07 12:45:41 +08:00
发下写的 gson 工具类, 可以参考


import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* <p>description:Gson 单例</p>
* <p>author:Leon</p>
* <p>date:2019/2/25 0025</p>
* <p>e-mail: deadogone@gmail.com</p>
*/
public class GsonUtils {
private static final GsonUtils INSTANCE = new GsonUtils();
private Gson gson;

private GsonUtils() {
gson = new Gson();
}

public static GsonUtils get() {
return INSTANCE;
}

public Gson gson() {
return gson;
}

public String toJson(Object obj) {
return gson.toJson(obj);
}


public <D> D fromJson(String json, Class<D> clazz) {
return gson.fromJson(json, clazz);
}

public <D> List<D> jsonToList(String json, Class<D[]> clazz) {
D[] array = gson.fromJson(json, clazz);
return Arrays.asList(array);
}

public <D> ArrayList<D> jsonToArrayList(String json, Class<D> clazz) {
Type type = new TypeToken<ArrayList<JsonObject>>() {
}.getType();
ArrayList<JsonObject> jsonObjects = gson.fromJson(json, type);

ArrayList<D> arrayList = new ArrayList<>();
for (JsonObject jsonObject : jsonObjects) {
arrayList.add(gson.fromJson(jsonObject, clazz));
}
return arrayList;
}
}
Helsing
2023-07-07 13:30:05 +08:00
可以换 kotlin 试试,有 reified 关键字
OpenJdk
2023-07-11 14:03:49 +08:00
不知道你用的什么 JSON 序列化工具。
OpenJdk
2023-07-11 14:07:53 +08:00
不知道你用的什么 JSON 序列化工具。
但是 Jackson 是通过在父类上打注解以字段值判定的形式来指定反序列化使用哪个具体的子类。
看看 @JsonTypeInfo 和 @JsonSubTypes 注解。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/954727

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX