
本文探讨了在使用jackson库进行json多态反序列化时,如何处理类型标识符不是固定字段名而是动态键值对的情况。当json结构中对象的类型信息以某个字段的“值”而非固定“属性名”来指示时,标准的`@jsontypeinfo`注解无法直接满足需求。文章详细介绍了通过实现自定义`jsondeserializer`来解析这类非标准json结构,并提供了具体的j*a代码示例,包括数据模型定义、反序列化器实现及测试用例,同时指出了该方案的优点与局限性。
在J*a开发中,处理JSON数据是常见的任务,而Jackson是广泛使用的JSON处理库。当我们需要将包含多态对象的JSON字符串反序列化为具体的J*a对象时,Jackson提供了@JsonTypeInfo和@JsonSubTypes等注解来简化这一过程。然而,这些标准机制通常要求JSON中有一个固定的属性(例如"type")来指示对象的实际类型。
考虑以下JSON结构:
{
"bulli": "dog",
"barkVolume": 10
}
{
"kitty": "cat",
"likesCream": true,
"lives": 3
}在这个结构中,"bulli"和"kitty"是对象的实例名称,而它们对应的值"dog"和"cat"则表示了对象的具体类型。这种情况下,类型标识符并非一个固定的属性名,而是由某个动态键(如"bulli"或"kitty")所对应的值来决定。传统的@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type")机制无法直接处理这种动态键值对作为类型标识的情况,因为它期望一个名为"type"的固定属性。
为了解决上述问题,我们需要实现一个自定义的JsonDeserializer。这种方法允许我们完全控制JSON解析过程,从而能够灵活地处理非标准或复杂的数据结构。
首先,我们定义抽象的基类Animal以及其具体的子类Dog和Cat。关键在于在Animal类上使用@JsonDeserialize(using = AnimalDeserializer.class)注解,将自定义的反序列化器关联到该抽象类。同时,为了避免在反序列化过程中遇到未知属性导致错误,可以在Animal类上添加@JsonIgnoreProperties(ignoreUnknown=true)。
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
// 抽象基类 Animal,指定自定义反序列化器
@JsonDeserialize(using = AnimalDeserializer.class)
@JsonIgnoreProperties(ignoreUnknown = true) // 忽略JSON中未映射的字段
public abstract class Animal {
public String name; // 动物的名称,将由动态键提供
}
// Dog 类
public class Dog extends Animal {
@JsonProperty
public int barkVolume;
}
// Cat 类
public class Cat extends Animal {
@JsonProperty
public boolean likesCream;
@JsonProperty
public int lives;
}AnimalDeserializer是解决问题的核心。它将负责解析JSON节点,识别出表示动物类型的值,并根据该值将整个节点映射到正确的子类实例。
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import j*a.io.IOException;
import j*a.util.Iterator;
public class AnimalDeserializer extends JsonDeserializer<Animal> {
@Override
public Animal deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
// 获取 ObjectMapper 实例,用于后续的节点到对象转换
ObjectMapper mapper = (ObjectMapper) jsonParser.getCodec();
// 将当前JSON节点读取为 ObjectNode,以便遍历其字段
ObjectNode node = mapper.readTree(jsonParser);
// 遍历 ObjectNode 中的所有字段名
Iterator<String> fieldIterator = node.fieldNames();
while (fieldIterator.hasNext()) {
String fieldName = fieldIterator.next();
// 检查当前字段的值是否为 "dog" (不区分大小写)
if (node.get(fieldName).asText().equalsIgnoreCase("dog")) {
// 如果是 "dog",则将整个节点映射到 Dog 类
Dog dog = mapper.treeToValue(node, Dog.class);
// 将识别出的动态键作为动物的名称
dog.name = fieldName;
return dog;
}
// 检查当前字段的值是否为 "cat" (不区分大小写)
else if (node.get(fieldName).asText().equalsIgnoreCase("cat")) {
// 如果是 "cat",则将整个节点映射到 Cat 类
Cat cat = mapper.treeToValue(node, Cat.class);
// 将识别出的动态键作为动物的名称
cat.name = fieldName;
return cat;
}
}
// 如果遍历完所有字段仍未识别出动物类型,则抛出异常
throw new IllegalArgumentException("无法识别的动物类型");
}
}在AnimalDeserializer中,主要逻辑如下:
Magician
Figma插件,AI生成图标、图片和UX文案
412
查看详情
为了测试这个自定义的反序列化器,我们可以创建一个包含多个动物对象的JSON数组,并使用ObjectMapper进行反序列化。
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import j*a.util.List;
public class Farm {
private static final String json = "[" +
"{\"bulli\":\"dog\",\"barkVolume\":10},\n" +
"{\"dogi\":\"dog\", \"barkVolume\":7},\n" +
"{\"kitty\":\"cat\", \"likesCream\":true, \"lives\":3},\n" +
"{\"milkey\":\"cat\", \"likesCream\":false, \"lives\":9}" +
"]";
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
// 使用 TypeReference 反序列化为 List<Animal>
List<Animal> animals = mapper.readValue(json, new TypeReference<List<Animal>>() {});
// 遍历并打印反序列化后的动物信息
animals.forEach(a -> {
System.out.println("动物名称: " + a.name);
if (a instanceof Dog) {
Dog dog = (Dog) a;
System.out.println(" 类型: 狗, 叫声大小: " + dog.barkVolume);
} else if (a instanceof Cat) {
Cat cat = (Cat) a;
System.out.println(" 类型: 猫, 是否喜欢奶油: " + cat.likesCream + ", 生命数: " + cat.lives);
}
System.out.println("---");
});
}
}运行Farm类的main方法,将输出如下结果:
动物名称: bulli 类型: 狗, 叫声大小: 10 --- 动物名称: dogi 类型: 狗, 叫声大小: 7 --- 动物名称: kitty 类型: 猫, 是否喜欢奶油: true, 生命数: 3 --- 动物名称: milkey 类型: 猫, 是否喜欢奶油: false, 生命数: 9 ---
这表明自定义的反序列化器成功地将具有动态类型键的JSON数据映射到了正确的J*a多态对象。
虽然自定义JsonDeserializer为处理非标准JSON结构提供了强大的灵活性,但这种方法也伴随着一些潜在的问题和需要注意的事项:
当面对JSON数据中类型标识符并非固定属性名,而是由动态键值对指示的多态结构时,Jackson的标准注解机制将无法直接满足需求。通过实现一个自定义的JsonDeserializer,我们可以完全控制反序列化过程,从而灵活地解析这些非标准格式。尽管这种方法提供了强大的灵活性,但也需要注意其在类型误判、手动字段设置和可维护性方面的潜在挑战。在选择此方案时,应权衡其带来的灵活性与潜在的复杂性,并确保JSON结构的特殊性确实需要这种定制化的处理方式。
以上就是Jackson自定义反序列化实现动态类型键的JSON多态处理的详细内容,更多请关注其它相关文章!
# 键值
# 谷歌seo内容写作
# 网站推广营销团队分工
# seo适合女人学吗
# 巩义视频营销推广
# 本溪长尾关键词排名
# 崂山关键词排名工具
# 优质推广营销方案
# 杭州散装白酒网站建设
# 兰州网站推广蔚訫hfqjwl下拉
# 合肥网站优化哪个最好
# 是由
# 在这个
# 非标准
# 数据结构
# java
# 子类
# 多态
# 遍历
# 序列化
# 自定义
# json数组
# 键值对
# json处理
# java开发
# ai
# app
# node
# json
# js
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
Teambition网盘如何共享文件
使用Selenium在无头Chrome中交互动态菜单和复选框的策略
J*aScript实现下拉菜单驱动的动态表格数据展示
电脑从睡眠中被自动唤醒怎么办_Windows唤醒源事件查看与禁用【解决】
Lar*el 中高效执行多列更新:单次查询实现
三星A55应用闪退排查步骤_Samsung A55稳定性优化技巧
Python中深度嵌套字典与列表的数据提取与条件过滤指南
苹果手机如何清理系统缓存数据 iPhone非越狱清理垃圾文件的技巧【系统优化】
pubmed数据库官方主页_pubmed学术论文查找官网直达
使用逻辑应用(Logic Apps)自动处理邮件附件中的XML到Excel
win11讲述人怎么关闭 Win11屏幕朗读辅助功能禁用方法【技巧】
mysql数据库索引类型有哪些_mysql索引类型解析
管理打开的编辑器:固定、分组和关闭技巧
微信网页版在线登录 微信网页版在线使用入口
sublime怎么快速在浏览器中预览HTML_sublime配置View in Browser教程
mysql如何回滚事务_mysql ROLLBACK事务回滚方法
小红书网页版在线直达 小红书网页版免费登录入口
谷歌学术论文搜索引擎 谷歌学术官网入口论坛永久链接
企查查官网和爱企查 企查查企业查询官网入口
使用CSS :has() 选择器实现父元素样式控制:从子元素反向应用样式
J*aScript二进制处理_ArrayBuffer与Blob
PHP中动态类名访问的类实例类型提示与静态分析实践
j*a中赋值运算符是什么?
windows10怎么更改下载路径_windows10默认存储位置修改教程
《海底捞》点外卖方法
PHP utf8_encode 字符编码转换疑难解析与最佳实践
惠普电脑BIOS界面看不懂怎么办_HP电脑BIOS功能选项解读与设置
解决VS Code中Python版本冲突与输出异常的指南
AO3永久镜像入口开放_AO3最新网址兼容所有浏览器
Golang如何使用log记录日志信息_Golang log日志记录方法总结
获取WooCommerce产品在后台编辑页面的分类ID
荣耀盒子应用管理技巧
J*aScript字符串_Unicode处理
Win11怎么开启HDR_Windows 11显示器画质增强设置
飞飞漫画漫画阅读官网_飞飞漫画漫画阅读官网进入阅读
微信步数怎么刷_微信步数快速提升技巧
歌词怎么展示在|直播|间视频号?有什么注意事项?
重返未来:1999卡戎全方位攻略
Go语言中方法接收器的选择:值类型还是指针类型?
POKI小游戏在线免费入口链接 POKI小游戏无下载秒玩玩
韩剧圈正版官网入口_韩剧圈官方指定登录
《下一站江湖2》独孤剑诀习得方法
WooCommerce 新客户订单自动添加管理员备注教程
百度输入法在AutoCAD中无法输入中文怎么办_百度输入法CAD输入异常解决方法
哔哩哔哩黑名单怎么查看
《气泡星球》兑换码礼包大全
OPPO手机参数配置如何开启护眼模式_OPPO手机参数配置护眼模式开启指南
支付宝如何解绑云闪付_支付宝与云闪付账户关联解除方法
《合金装备4》有望推出重制版!制作人发话了
圆通快递官方入口不需要登录 在线查询入口快速查询
2025-12-04
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。