Java JSON反序列化:如何将外层字段映射到内层嵌套类属性
问题描述
现有如下结构的JSON待解析:
{ "outer-field":{ "outer-a":"something", "outer-b":12345678, "inner-field":{ "inner-a":false, "inner-b":0.0, "inner-c":29.99 } } }
最初编写的映射实体类如下:
public class OuterObject { @JsonProperty("outer-a") public String outerA; @JsonProperty("outer-b") public Integer outerB; @JsonProperty("inner-field") public InnerObject innerField; } public class InnerObject{ @JsonProperty("inner-a") public Boolean innerA; @JsonProperty("inner-b") public Double innerB; @JsonProperty("inner-c") public Double innerC; }
需求是不编写全量自定义反序列化逻辑,通过自定义setter、注解等轻量方式,将外层层级的字段直接映射保存到内层对象中,目标代码结构如下:
public class InnerObject{ @JsonProperty("inner-a") public Boolean innerA; @JsonProperty("inner-b") public Double innerB; @JsonProperty("inner-c") public Double innerC; // 期望直接映射外层的outer-a字段 public String outerA; }
补充说明:由于待处理JSON结构复杂度较高,全量自定义反序列化逻辑为最后备选方案。
可行方案
直接在InnerObject字段上标记外层字段名的@JsonProperty注解无法生效,Jackson默认只会在当前解析的JSON节点层级查找匹配属性,不会自动读取父级节点的字段,可通过以下两种轻量方案实现需求,均不需要编写全量反序列化逻辑:
方案1:外层类编写传导setter(适合下沉字段少的场景)
仅需在OuterObject中给需要下沉的外层字段编写专属setter,解析到对应外层字段时直接赋值给内层对象的对应属性即可,不需要修改InnerObject的原有注解逻辑,性能和原生注解解析几乎一致。
示例代码:public class OuterObject { // 不需要下沉的外层字段保持原有映射逻辑即可 @JsonProperty("outer-b") public Integer outerB; public InnerObject innerField; // 解析到外层的outer-a字段时,直接赋值给内层对象 @JsonProperty("outer-a") public void setOuterA(String outerA) { if (innerField == null) { innerField = new InnerObject(); } innerField.outerA = outerA; } // 正常映射内层对象,注意判空避免空指针 @JsonProperty("inner-field") public void setInnerField(InnerObject innerField) { this.innerField = innerField; } }Jackson反序列化时会自动识别字段对应的setter方法,不需要额外配置,只要注意解析顺序可能带来的空指针问题,提前初始化内层对象即可。
方案2:自定义轻量反序列化后置处理器(适合下沉字段多、结构复杂的场景)
如果需要下沉的字段数量多,一个个写传导setter维护成本高,可以实现一个通用的Bean反序列化扩展器,仅在内层对象默认反序列化完成后,从解析上下文的父节点读取需要下沉的字段赋值,不需要手动处理每个字段的类型解析逻辑。
实现步骤:- 定义一个简单的标记注解,用来标注InnerObject中需要从外层映射的字段,指定对应的外层字段名
- 注册
BeanDeserializerModifier扩展,拦截InnerObject的反序列化过程,在默认反序列化完成后,通过JsonParser获取当前节点的父节点(也就是外层的outer-field节点),读取标注了注解的字段对应的值,赋值给InnerObject实例即可。
该方案一次配置后,后续新增需要下沉的字段只需要在InnerObject中加对应注解即可,维护成本极低,也不需要改动外层类的代码。
内容的提问来源于stack exchange,提问作者Snake_NG
相关产品推荐
相关产品推荐

