Json 解析丢失子类信息 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
nnegier
V2EX    Java

Json 解析丢失子类信息

  •  
  •   nnegier 2023-07-07 08:12:58 +08:00 3093 次点击
    这是一个创建于 902 天前的主题,其中的信息可能已经有所发展或是发生改变。

    子类们的共同父类:BasePlugin

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

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

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

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

    这个有能解决吗?

    第 1 条附言    2023-07-07 20:03:34 +08:00
    #6 6 楼答案有效
    12 条回复    2023-07-11 14:07:53 +08:00
    chendy
        1
    chendy  
       2023-07-07 08:20:25 +08:00
    koloonps
        2
    koloonps  
       2023-07-07 09:08:40 +08:00
    new ObjectMapper().readValue("", new TypeReference<Object>() {
    @Override
    public Type getType() {
    return super.getType();
    }
    })
    AoEiuV020JP
        3
    AoEiuV020JP  
       2023-07-07 10:08:47 +08:00
    讲道理,仔细想想, 如果可以从父类泛型这样得到子类的属性,那人家直接内置一个,
    Type type = new TypeToken<List<Object>>() {
    }.getType();
    压根都不需要暴露出 TypeToken 了,

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

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

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

    ( csdn)

    但印象这个有安全性问题
    Leon406
        9
    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: [email protected]</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
        10
    Helsing  
       2023-07-07 13:30:05 +08:00 via iPhone
    可以换 kotlin 试试,有 reified 关键字
    OpenJdk
        11
    OpenJdk  
       2023-07-11 14:03:49 +08:00
    不知道你用的什么 JSON 序列化工具。
    OpenJdk
        12
    OpenJdk  
       2023-07-11 14:07:53 +08:00
    不知道你用的什么 JSON 序列化工具。
    但是 Jackson 是通过在父类上打注解以字段值判定的形式来指定反序列化使用哪个具体的子类。
    看看 @JsonTypeInfo 和 @JsonSubTypes 注解。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4008 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 05:16 PVG 13:16 LAX 21:16 JFK 00:16
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86