
本教程旨在解决java应用中处理json数据时遇到的动态键名问题。当json响应的顶层键名不固定,而是根据请求参数变化时,传统的静态pojo结构将失效。文章详细介绍了如何利用jackson库的@jsonanysetter和@jsonanygetter注解,结合map数据结构,构建一个能够灵活解析和序列化任意动态json键的pojo,同时探讨了如何处理字段缺失和空值序列化的情况,从而提升应用的健壮性和适应性。
背景:动态JSON键的挑战
在与外部API集成时,我们经常会遇到JSON响应的结构不完全固定的情况。特别是当JSON对象的顶级键名不是预设的常量,而是根据请求参数动态生成时,传统的Java POJO(Plain Old Java Object)映射方式便会遇到挑战。
例如,考虑以下JSON响应结构,其中”EU”和”AU”是动态的键名,它们的值都是一个包含IndexCalendarDateResponseWrapper对象的列表:
{ "EU": [ { "calId": "EU", "calDate": "2022-11-01", "prevBusinessDay": "2022-11-01", "nextBusinessDay": "2022-11-01", "businessDay": true, "monthEndBusinessDay": false } ], "AU": [ { "calId": "AU", "calDate": "2022-11-01", "prevBusinessDay": "2022-11-01", "nextBusinessDay": "2022-11-01", "businessDay": true, "monthEndBusinessDay": false } ]}
如果尝试使用以下静态POJO来映射,当JSON中的键名变为”JU”、”BU”等其他值时,该POJO将无法正确解析这些动态部分,导致数据丢失或解析失败。
@Data@AllArgsConstructor@NoArgsConstructorpublic class StaticIndexCalendarDateResponseBean { @JsonProperty("EU") private List EU; @JsonProperty("AU") private List AU; // ... 如果有更多动态键,需要不断添加字段,不具备扩展性}
这种静态映射的局限性在于,它要求我们预知所有可能的顶级键名。然而,在实际应用中,这些键名可能由API请求路径参数决定,数量和名称都可能动态变化。
核心解决方案:利用Jackson的`@JsonAnySetter`和`@JsonAnyGetter`
为了解决动态JSON键的问题,我们可以利用Jackson库提供的@JsonAnySetter和@JsonAnyGetter注解。这两个注解允许POJO在反序列化时捕获所有未映射的JSON属性,并在序列化时将动态数据重新输出为JSON属性。
1. 使用`Map`存储动态数据
首先,我们需要在POJO中定义一个Map来存储那些动态的键值对。在本例中,键是字符串(如”EU”, “AU”),值是IndexCalendarDateResponseWrapper对象的列表。
MarsX
AI驱动快速构建App,低代码无代码开发,改变软件开发的游戏规则
159 查看详情
import com.fasterxml.jackson.annotation.JsonAnyGetter;import com.fasterxml.jackson.annotation.JsonAnySetter;import java.util.HashMap;import java.util.List;import java.util.Map;public class DynamicIndexCalendarDateResponseBean { private Map<String, List> responseWrappers = new HashMap(); // ... 后续添加 @JsonAnySetter 和 @JsonAnyGetter 方法}
2. 使用`@JsonAnySetter`进行反序列化
@JsonAnySetter注解用于标记一个方法,该方法将接收JSON中所有未被其他字段显式映射的属性。当Jackson反序列化JSON时,如果遇到POJO中没有对应字段的属性,它会调用被@JsonAnySetter标记的方法,并将属性名作为String参数,属性值作为第二个参数(其类型应与Map的值类型兼容)传递给该方法。
@JsonAnySetter public void readResponseWrappers(String key, List value) { responseWrappers.put(key, value); }
通过这个方法,无论JSON中出现”EU”、”AU”、”JU”或任何其他键,只要其值是List类型,Jackson都能将其捕获并存储到responseWrappers这个Map中。
3. 使用`@JsonAnyGetter`进行序列化
为了能够将这个动态POJO重新序列化回JSON,并保持动态键的结构,我们需要使用@JsonAnyGetter注解。它标记一个方法,该方法返回一个Map,Jackson会遍历这个Map,将其中的键值对作为顶层属性添加到输出的JSON中。
@JsonAnyGetter public Map<String, List> writeResponseWrappers() { return responseWrappers; }
这样,当DynamicIndexCalendarDateResponseBean对象被序列化时,responseWrappers中存储的所有动态键值对都将以原始的JSON结构输出。
完整的动态POJO示例
结合上述注解,完整的动态POJO如下所示:
import com.fasterxml.jackson.annotation.JsonAnyGetter;import com.
以上就是掌握Jackson:构建可动态适应任意JSON键的POJO的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/865307.html
微信扫一扫
支付宝扫一扫