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

2020-10-13 01:29:01 +08:00
 sdbybyd

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 类型识别不出来

3823 次点击
所在节点    Java
17 条回复
Cbdy
2020-10-13 06:58:49 +08:00
xuanbg
2020-10-13 07:14:23 +08:00
把 List<String>封装成一个对象
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
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
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
2020-10-13 09:02:13 +08:00
mapper.readValue(str, new TypeReference<Channel<Item>>() {});
就行了

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

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

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

这么写
{
"condition": {
"class": "com.github.Test",
"id": {
"uid": 1000
},
"source": 1
}
}
sdbybyd
2020-10-13 11:56:22 +08:00
统一回复,使用 JsonNode 临时解决了,不能推断的泛型字段单独读取 string 出来后再重新反序列化(这时 JavaType 或 TypeReference 都可以)

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

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

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

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

© 2021 V2EX