V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
sdbybyd
V2EX  ›  Java

请教大家 Jackson 泛型反序列化问题

  •  
  •   sdbybyd · 2020-10-13 01:29:01 +08:00 · 3824 次点击
    这是一个创建于 1503 天前的主题,其中的信息可能已经有所发展或是发生改变。
    
    class R<T> {
      private T data;
    }
    
    class Item {
      private R<List<String>> message;
    }
    
    class Channel<T> {
      private T data;
    }
    
    
    Channel<Item> i ???
    

    请教下最后一个 Channel<Item> 要怎么反序列化呢?

    
                JavaType type = mapper.getTypeFactory()
                        .constructParametricType(
                                Channel.class,
                                Item.class);
                Channel<Item> body = mapper.readValue(str, type);
    

    这样做的话报错,R 类型识别不出来

    17 条回复    2020-10-13 11:56:22 +08:00
    Cbdy
        1
    Cbdy  
       2020-10-13 06:58:49 +08:00 via Android
    xuanbg
        2
    xuanbg  
       2020-10-13 07:14:23 +08:00
    把 List<String>封装成一个对象
    xuanbg
        3
    xuanbg  
       2020-10-13 07:50:14 +08:00
    @xuanbg 看错题目了,你这个泛型嵌套,获取 type 也要嵌套啊,哪能一下子就得到完整的类型呢。试试看下面的代码
    JavaType r = mapper.getTypeFactory().constructParametricType(R.class, String.class);
    JavaType i = mapper.getTypeFactory().constructParametricType(Item.class, r);
    JavaType c = mapper.getTypeFactory().constructParametricType(Channel.class, i);

    Channel<Item> body = mapper.readValue(str, c);
    xuanbg
        4
    xuanbg  
       2020-10-13 07:51:50 +08:00
    还是写错了……

    @xuanbg 看错题目了,你这个泛型嵌套,获取 type 也要嵌套啊,哪能一下子就得到完整的类型呢。试试看下面的代码
    JavaType r = mapper.getTypeFactory().constructParametricType(List.class, String.class);
    JavaType i = mapper.getTypeFactory().constructParametricType(Item.class, r);
    JavaType c = mapper.getTypeFactory().constructParametricType(Channel.class, i);

    Channel<Item> body = mapper.readValue(str, c);
    xuanbg
        5
    xuanbg  
       2020-10-13 07:54:15 +08:00
    好吧……

    JavaType list = mapper.getTypeFactory().constructParametricType(List.class, String.class);
    JavaType r = mapper.getTypeFactory().constructParametricType(R.class, list);
    JavaType item = mapper.getTypeFactory().constructParametricType(Item.class, r);
    JavaType channel = mapper.getTypeFactory().constructParametricType(Channel.class, i);
    qwerthhusn
        6
    qwerthhusn  
       2020-10-13 09:02:13 +08:00
    mapper.readValue(str, new TypeReference<Channel<Item>>() {});
    就行了

    Item 里面的泛型 Jackson 能取到的,你不用关心
    passerbytiny
        7
    passerbytiny  
       2020-10-13 09:12:00 +08:00 via Android
    Class 类型的方法参数,实参只接受真实类型,不接受泛型。
    90d0n
        8
    90d0n  
       2020-10-13 09:17:57 +08:00
    new TypeReference<Channel<Item>>() {}
    qinxi
        9
    qinxi  
       2020-10-13 09:30:16 +08:00
    0x666666
        10
    0x666666  
       2020-10-13 09:57:12 +08:00
    楼上说的对,遇到泛型统一 TypeReference 解决就完事了
    GM
        11
    GM  
       2020-10-13 09:58:15 +08:00
    两个方法:
    一个是楼上说的 new TypeReference<Channel<Item>>() {}
    第二个,简单粗暴,直接定义一个类:
    public static class ChannelItem extends Channel<Item> {}

    后续所有序列化、反序列化都用这个 ChannelItem
    sdbybyd
        12
    sdbybyd  
    OP
       2020-10-13 11:17:36 +08:00
    @Cbdy @90d0n @GM TypeReference 只能推断顶层类型,会报错,数据成员泛型怎么推断呢?
    sdbybyd
        13
    sdbybyd  
    OP
       2020-10-13 11:30:57 +08:00
    @xuanbg 你这个是嵌套泛型的做法,但是仔细看下数据成员是泛型怎么搞呢?
    Elroooo0Y
        14
    Elroooo0Y  
       2020-10-13 11:32:38 +08:00
    item 上面不加泛型
    自己的都不知道 R 的具体类型是什么
    jackson 怎么会知道呢 .

    如果 R 不能表示出来的话 可以在 json 字符里面试试 "class"关键字表示一下具体的泛型类型
    sdbybyd
        15
    sdbybyd  
    OP
       2020-10-13 11:34:36 +08:00
    @qinxi 你这个是多态时的做法,不能用于复杂泛型吧
    Elroooo0Y
        16
    Elroooo0Y  
       2020-10-13 11:42:18 +08:00
    @Elroooo0Y

    这么写
    {
    "condition": {
    "class": "com.github.Test",
    "id": {
    "uid": 1000
    },
    "source": 1
    }
    }
    sdbybyd
        17
    sdbybyd  
    OP
       2020-10-13 11:56:22 +08:00
    统一回复,使用 JsonNode 临时解决了,不能推断的泛型字段单独读取 string 出来后再重新反序列化(这时 JavaType 或 TypeReference 都可以)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1580 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:48 · PVG 00:48 · LAX 08:48 · JFK 11:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.