当前位置: 首页 > news >正文

一种JSON多态表示法

介绍

假设现在需要实现一种功能: 从某个远程的组件(消息队列或远程文件)拉取最后几条记录做一个展示.

需要支持如下的组件:

  • Kafka

  • RocketMQ

  • OSS

  • 假设还有很多, 这里不列了 …

显然, 每种组件需要的参数各不一样, 那么此时如何使用一个统一的结构来表达这些组件的参数呢?

刚遇到这个这个需求时, 感觉它和 Java 里常遇到的 多态JSON 序列化很像(确实).
但在实践中, 我们这份配置需要被多种编程语言的程序使用, 我们需要考虑各个语言解析多态JSON的难度.
因此我们尽量选择一种简单的通用的做法, 不依赖特殊的json特性, 也就是本文介绍的方法2.

方法1 使用通用 map 结构

这也是一种常见做法.

使用 map<string, object> 结构来存储相关参数, 同时约定加入一个字段 type = “组件名”, 使得使用者知道是哪个组件.
比如

{
	"type": "kafka",
	"brokers": ["aaa", "bbb"],
	"topic": "xxx-topic",
	"advancedOptions": {
		"auth": {
			...
		}
	}
}

优点:

  1. 序列化简单
  2. 添加新类型不用修改结构体
  3. 没有使用特殊的 json 特性

缺点:

  1. 弱类型: 操作没有静态类型方便
  2. 遇到嵌套结构时, 处理起来有点麻烦 …

如果你要将这种方式与静态类型结合, 那么通常避免不了要反序列化 2 次: 先把 type 解析出来知道具体类型, 然后再对着具体类型反序列化一次.

如果这个行为不频繁, 那反序列化 2 次完全是可以接受的.

方法2 使用静态类型

{
	"type": "kafka",
	"kafka": {
		// 这里存放 kafka 特有的配置
		"brokers": ["aaa", "bbb"],
		"topic": "xxx-topic",
		"advancedOptions": {
			"auth": {
				...
			}
		}
	}
}

想要解析这个json的人最好准备一个 class 去承担反序列化

class FromComponent {
    // type 的取值是 kafka / rocketMQ / oss
    // 当然也可以约定枚举值必须是大写, 从而使用 KAFKA ROCKET_MQ OSS
    // 总之 type 能和 具体的字段对上就行
	String type;
	KafkaConf kakfa;
    RocketMQConf rocketMQ;
    OSSConf oss;
    // 将来可能继续增加 ...
}

优点:

  1. 静态强类型
  2. 只需要反序列化一次

缺点:

  1. 使用的时候需要先判断 type 再去取对应的字段值 (不算是缺点, 其他方案也未必能少得了这个步骤 或者判断 instanceOf)
  2. 由于是静态类型, 在 FromComponent 里需要写上所有可能得 type 以及这些 type 对应的配置结构体, 如上面的 kafka/rocketMQ/oss …
  3. 添加新类型时需要到这里加字段

我觉得上面的缺点都不算特别不可接受.
当需要修改或新增类型时, 最大的工作肯定不是在于配置描述, 而是在对应的处理实现上.

其他

如果你曾经尝试过 Java 里的多态JSON序列化, 那么你可能会遇到如下的表示法:

{
	"type": "kafka"
	"from": {kafka的配置...}
}
{
	"type": "oss"
	"from": {oss的配置...}
}
{
	"kafka": {kafka的配置...}
}
{
	"oss": {oss的配置...}
}

这种方法在实践中可以解决序列化问题, 但实际使用的时候依旧少不了 instanceOf, 总之你需要先判断一下再转类型到子类.
那跟方法2里的先判断一下 type 再选取对应的字段, 理论上没有任何区别.
而且要注意方法2不需要json框架支持多态反序列化.

相关文章:

  • UniApp的神器-开启前端开发的全新篇章
  • 解决ModuleNotFoundError: No module named ‘distutils‘
  • xiaomi pad 6PRO 小米平板6 pro hyperOS降级 澎湃os 降级MIUI 14 教程 免解锁BL 降级,168小时解锁绑定
  • Xcode数据分析与可视化:解锁应用优化的密钥
  • linux操作两个文件,a里的数据删b
  • rust交叉编译
  • 【linux】linux中如何通过systemctl来创建和管理服务
  • 电销机器人引领电销变革
  • servlet的执行顺序
  • 初探 Rust 语言与环境搭建
  • 多功能声学馆的卓越优势:剧院级音效的全新体验—轻空间
  • 【游戏引擎之路】登神长阶(九)——《3D游戏编程大师技巧》:我想成为游戏之神!
  • 【Python学习-UI界面】PyQt5 小部件1-Label
  • WPF-实现多语言的静态(需重启)与动态切换(不用重启)
  • 前端 JavaScript 的 _ 语法是个什么鬼?
  • 自建Gitlab和Gitlab runner并推送镜像到Harbor
  • 学习STM32(6)-- STM32单片机ADCDAC的应用
  • Halcon图像平滑与去噪
  • 关系,条件和逻辑操作符详解
  • Kafka系列之:Dead Letter Queue死信队列DLQ
  • 姚洋将全职加盟上海财经大学,担任滴水湖高级金融学院院长
  • 著名蒙古族音乐学者马•斯尔古愣逝世,享年86岁
  • 人民财评:网售“婴儿高跟鞋”?不能让畸形审美侵蚀孩子身心
  • 北外滩集团21.6亿元摘上海虹口地块,为《酱园弄》取景地
  • 看展览|2025影像上海艺博会:市场与当代媒介中的摄影
  • 七大交响乐团在沪“神仙斗法”,时代交响奏出何等时代新声