添加Instant自定义序列化器后JsonNode调用toString报错如何解决?
问题根因分析
- 自定义序列化器实现错误:你编写的
InstantSerializer中调用了jgen.writeEmbeddedObject(value)方法,该方法不会将Instant实例转换为标准JSON格式(字符串/时间戳),而是直接将Instant对象作为POJO嵌入到JsonNode中,生成POJONode类型节点,没有完成实际的序列化转换。 - JsonNode.toString()序列化逻辑限制:调用
JsonNode.toString()方法时,Jackson内部会使用独立的默认序列化逻辑输出节点内容,序列化POJONode中存储的Instant对象时,不会复用你给外部ObjectMapper注册的序列化规则,识别到Java 8时间类型时就会抛出缺少JSR310模块的报错。 - 自定义模块覆盖了JavaTimeModule的规则:你在注册
JavaTimeModule之后又注册了包含自定义Instant序列化/反序列化器的自定义模块,JavaTimeModule中默认的Instant序列化逻辑被自定义实现覆盖,不会生效。
修复方案
可根据实际需求选择以下任意一种方案:
方案1:修改自定义序列化器实现(推荐)
调整InstantSerializer的序列化逻辑,直接输出标准JSON格式,不再使用writeEmbeddedObject:
@Override public void serialize(Instant value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { // 示例:输出ISO8601格式字符串,需要输出时间戳可改为jgen.writeNumber(value.toEpochMilli()) jgen.writeString(value.toString()); }
修改后序列化生成的JsonNode为标准字符串/数值节点,调用toString()方法时不会触发POJO序列化逻辑,即可解决报错。
方案2:删除自定义Instant序列化/反序列化器
如果JavaTimeModule默认的序列化逻辑能够满足业务需求,直接删除自定义模块中Instant序列化/反序列化器的注册代码即可,JavaTimeModule默认已提供的Instant序列化、反序列化实现可直接适配需求。
方案3:使用自定义配置的ObjectMapper序列化JsonNode
如果业务必须保留POJONode存储Instant对象的逻辑,不要调用JsonNode.toString(),改为使用你配置好的MAPPER实例序列化JsonNode:
@Test public void test() { A a = new A(); a.setTime(Instant.now()); final JsonNode jsonNode = MAPPER.readTree(a); // 替换原toString调用 System.out.println(MAPPER.writeValueAsString(jsonNode)); }
该方案下序列化时会复用你配置的序列化规则,不会触发默认序列化逻辑的报错。
内容的提问来源于stack exchange,提问作者Karunakar Reddy L
相关产品推荐
相关产品推荐

