Jackson 如何保存 Map 中 key 的类型信息

2020-07-13 12:11:52 +08:00
 JasonLaw

首先看以下代码了解问题。

PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder().build();
ObjectMapper objectMapper = JsonMapper.builder()
        .activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.EVERYTHING)
        .build();

// content 为`["Gender","FEMALE"]`,保存了类型信息
String content = objectMapper.writeValueAsString(Gender.FEMALE);
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder().build();
ObjectMapper objectMapper = JsonMapper.builder()
        .activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.EVERYTHING)
        .build();


Map<Gender, String> map = new HashMap<>();
map.put(Gender.FEMALE, "v1");

// content 为`["java.util.HashMap",{"FEMALE":"v1"}]`,并没有保存 Map 中 key 的类型信息
String content = objectMapper.writeValueAsString(map);

我的问题:Jackson 可以做到保存 Map 中 key 的类型信息吗?如果可以,应该怎么做呢?

我所做的尝试:

  1. 我尝试过配置 SerializationFeature,但是没有一个相关的 SerializationFeature 是可以实现这个功能的。
  2. 我发现objectMapper.writeValueAsString(Gender.FEMALE)使用的是TypeWrappedSerializer,最后调用StdScalarSerializer.serializeWithType(T value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer),因此保存了类型信息。但是objectMapper.writeValueAsString(map)不一样,在序列化 Map 中 key 的时候,最后会调用EnumKeySerializer.serialize(Object value, JsonGenerator g, SerializerProvider serializers),只是简单地调用了toString(),因此没有保存类型信息。
1815 次点击
所在节点    Java
7 条回复
xgfan
2020-07-13 12:55:53 +08:00
你这是要干啥啊,感觉你压根不需要 json 啊。
只是要一个类型安全的序列化 /反序列化的工具的话,没必要跟 json 死磕。
wysnylc
2020-07-13 13:06:07 +08:00
json 中结构只有 map 和数组,数据类型只有字符串和数值
所有的反序列化都是收到 json 字符串然后反推结构和数据类型
标准的序列化中是没有泛型的,甚至一些扩展实现的数据都会被抹掉比如实现 list 接口加个属性在里面的情况
JasonLaw
2020-07-13 13:09:44 +08:00
@xgfan 我现在是使用 String 替代枚举作为替代应急措施,但是我更希望 Jackson 自身能够实现"保存 Map 中 key 的类型信息",因为不能改用其他的序列化 /反序列化机制。
iyaozhen
2020-07-13 13:17:49 +08:00
你要是自己系统内部传输数据可以不用 json 呀,直接序列化就行

或者你需要 pb
iseki
2020-07-13 13:28:10 +08:00
自己编写序列化器吧,你需要自己考虑把类型信息放在哪和安全问题
passerbytiny
2020-07-13 13:37:21 +08:00
json 的 key,只能是值不能是对象;

java 对象转成 json 是不保真的,不光 key,所有类型信息都会丢;

json 转会 java 对象,需要额外指定 java 对象的类型;
passerbytiny
2020-07-13 13:56:30 +08:00
仔细一看,楼主用了多态类型检测器。这玩意不是 json 标准(至少现在不是),我觉得一般人用试验性内容是在给自己挖坑。参考当前 javascript 、php 与 java 、.NET 在前端的流行度,这种强类型的 json 试验,很难成为正式标准。

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

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

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

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

© 2021 V2EX