Jackson兼容新旧JSON:实现数字与Length类反序列化
兼容新旧JSON格式反序列化Length类的实现方案
你需要让Jackson同时支持两种格式反序列化Length类——既可以解析原始数字(旧格式{"length":0.025}),也能解析包含m字段的对象(新格式{"length":{"m":0.025}})。之前尝试的几种方案都只适配了单一格式,下面是可行的实现方式:
方法:自定义Json反序列化器
通过自定义Jackson反序列化器,我们可以在解析时判断输入的JSON类型,分别处理数字和对象两种情况:
- 实现自定义反序列化器
import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.JsonDeserializer import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.node.NumericNode class LengthDeserializer : JsonDeserializer<Length>() { override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Length { val node: JsonNode = p.codec.readTree(p) return if (node is NumericNode) { // 处理旧格式:直接数字,当作米单位 node.asDouble().m } else { // 处理新格式:解析m字段的值 node.get("m").asDouble().m } } }
- 在Length类上绑定反序列化器
修改Length类,添加注解指定使用自定义反序列化器:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize @JsonDeserialize(using = LengthDeserializer::class) data class Length(val m: Double) : Comparable<Length> { // 原有属性与方法保持不变 @get:JsonIgnore val km: Double get() = m / 1e3 @get:JsonIgnore val cm: Double get() = m / 1e-2 @get:JsonIgnore val mm: Double get() = m / 1e-3 operator fun plus(other: Length) = (this.m + other.m).m operator fun minus(other: Length) = (this.m - other.m).m operator fun unaryMinus() = (-this.m).m override fun compareTo(other: Length): Int { return this.m.compareTo(other.m) } }
完成修改后,两种JSON格式都能正常反序列化为目标实例:
- 旧格式
{"length":0.025}→SampleClassThatContainsALength(0.025.m) - 新格式
{"length":{"m":0.025}}→SampleClassThatContainsALength(0.025.m)
补充:序列化格式保持
原有的Length类结构会被Jackson正常序列化为带m字段的新格式,无需额外修改即可保持输出一致性。
内容的提问来源于stack exchange,提问作者vatbub
相关产品推荐
相关产品推荐

