Flink CDC系列之:Kafka的Debezium JSON 结构定义类DebeziumJsonStruct
这是一个 Debezium JSON 结构定义类,使用枚举来定义 Debezium JSON 格式的字段结构和位置信息。
类概述
java
public class DebeziumJsonStruct
这个类通过嵌套枚举定义了 Debezium JSON 格式的完整结构,包括字段名称和位置信息。
嵌套枚举详解
DebeziumStruct - 顶层结构
java
enum DebeziumStruct {
SCHEMA(0, "schema"),
PAYLOAD(1, "payload");
作用:定义 Debezium JSON 的顶层结构字段。
字段说明:
- SCHEMA(0, "schema"):表结构信息(位置0,字段名"schema")
- PAYLOAD(1, "payload"):数据负载信息(位置1,字段名"payload")
对应的 JSON 结构:
java
{
"schema": { ... }, // SCHEMA 字段
"payload": { ... } // PAYLOAD 字段
}
DebeziumPayload - 数据负载结构
java
enum DebeziumPayload {
BEFORE(0, "before"),
AFTER(1, "after"),
OPERATION(2, "op"),
SOURCE(3, "source");
作用:定义 payload 对象内部的字段结构。
字段说明:
- BEFORE(0, "before"):变更前的数据(位置0,字段名"before")
- AFTER(1, "after"):变更后的数据(位置1,字段名"after")
- OPERATION(2, "op"):操作类型(位置2,字段名"op")
- SOURCE(3, "source"):源数据库信息(位置3,字段名"source")
对应的 JSON 结构:
java
{
"payload": {
"before": { ... }, // BEFORE 字段
"after": { ... }, // AFTER 字段
"op": "c", // OPERATION 字段
"source": { ... } // SOURCE 字段
}
}
DebeziumSource - 源信息结构
java
enum DebeziumSource {
DATABASE(0, "db"),
TABLE(1, "table");
作用:定义 source 对象内部的字段结构。
字段说明:
- DATABASE(0, "db"):数据库名称(位置0,字段名"db")
- TABLE(1, "table"):表名称(位置1,字段名"table")
对应的 JSON 结构:
java
{
"source": {
"db": "inventory", // DATABASE 字段
"table": "users" // TABLE 字段
}
}
枚举设计特点
位置和名称双重映射
java
private final int position; // 位置索引
private final String fieldName; // 字段名称
优势:
- 可以通过位置快速访问
- 可以通过名称清晰标识
类型安全
使用枚举替代字符串常量,避免拼写错误:
java
// 安全的方式
DebeziumPayload.BEFORE.getFieldName() // 返回 "before"
// 不安全的方式(容易拼错)
String field = "befor"; // 拼写错误
易于扩展
添加新字段只需在对应枚举中添加新值:
java
enum DebeziumPayload {
// 现有字段...
TIMESTAMP(4, "ts_ms"), // 新增时间戳字段
TRANSACTION(5, "transaction"); // 新增事务字段
实际使用场景
在序列化器中的使用
java
public class DebeziumJsonSerializationSchema {
public byte[] serialize(Event event) {
// 构建 Debezium JSON 结构
ObjectNode rootNode = objectMapper.createObjectNode();
// 使用枚举确保字段名称一致
rootNode.set(
DebeziumStruct.SCHEMA.getFieldName(),
buildSchemaNode()
);
rootNode.set(
DebeziumStruct.PAYLOAD.getFieldName(),
buildPayloadNode(event)
);
return objectMapper.writeValueAsBytes(rootNode);
}
private ObjectNode buildPayloadNode(Event event) {
ObjectNode payloadNode = objectMapper.createObjectNode();
// 设置操作类型
payloadNode.put(
DebeziumPayload.OPERATION.getFieldName(),
getOperationCode(event.op())
);
// 设置前后数据
payloadNode.set(
DebeziumPayload.BEFORE.getFieldName(),
convertToJson(event.before())
);
payloadNode.set(
DebeziumPayload.AFTER.getFieldName(),
convertToJson(event.after())
);
// 设置源信息
payloadNode.set(
DebeziumPayload.SOURCE.getFieldName(),
buildSourceNode(event.tableId())
);
return payloadNode;
}
private ObjectNode buildSourceNode(TableId tableId) {
ObjectNode sourceNode = objectMapper.createObjectNode();
sourceNode.put(
DebeziumSource.DATABASE.getFieldName(),
tableId.getSchemaName()
);
sourceNode.put(
DebeziumSource.TABLE.getFieldName(),
tableId.getTableName()
);
return sourceNode;
}
}
在反序列化器中的使用
java
public class DebeziumJsonDeserializationSchema {
public Event deserialize(byte[] message) {
JsonNode rootNode = objectMapper.readTree(message);
// 使用枚举字段名获取节点
JsonNode payloadNode = rootNode.get(
DebeziumStruct.PAYLOAD.getFieldName()
);
// 解析操作类型
String operation = payloadNode.get(
DebeziumPayload.OPERATION.getFieldName()
).asText();
// 解析源信息
JsonNode sourceNode = payloadNode.get(
DebeziumPayload.SOURCE.getFieldName()
);
String database = sourceNode.get(
DebeziumSource.DATABASE.getFieldName()
).asText();
String table = sourceNode.get(
DebeziumSource.TABLE.getFieldName()
).asText();
// ... 其他解析逻辑
}
}
生成的完整 JSON 示例
基于这个结构定义,会生成如下格式的 JSON:
java
{
"schema": {
"type": "struct",
"fields": [
{
"type": "struct",
"fields": [
{"type": "int32", "optional": false, "field": "id"},
{"type": "string", "optional": true, "field": "name"}
],
"optional": true,
"name": "mysql-server-1.inventory.users.Value",
"field": "before"
}
],
"optional": false,
"name": "mysql-server-1.inventory.users.Envelope"
},
"payload": {
"before": null,
"after": {
"id": 1001,
"name": "张三"
},
"op": "c",
"source": {
"db": "inventory",
"table": "users"
}
}
}
扩展建议
当前定义比较基础,实际 Debezium 格式包含更多字段,可以扩展为:
java
enum DebeziumPayload {
BEFORE(0, "before"),
AFTER(1, "after"),
OPERATION(2, "op"),
SOURCE(3, "source"),
TIMESTAMP(4, "ts_ms"),
TRANSACTION(5, "transaction");
}
enum DebeziumSource {
DATABASE(0, "db"),
TABLE(1, "table"),
SERVER_ID(2, "server_id"),
BINLOG_FILE(3, "file"),
BINLOG_POSITION(4, "pos"),
CONNECTOR(5, "connector"),
SNAPSHOT(6, "snapshot");
}
总结:DebeziumJsonStruct 是一个结构定义类,它通过嵌套枚举:
✅ 定义标准结构:完整定义 Debezium JSON 格式的字段结构
✅ 提供类型安全:使用枚举替代字符串常量,避免拼写错误
✅ 支持双向访问:既可以通过名称访问,也可以通过位置访问
✅ 易于维护扩展:集中管理字段定义,支持轻松添加新字段
✅ 提高代码可读性:清晰的枚举名称使代码意图更明确
这个类是 Debezium JSON 序列化和反序列化组件的基础,确保了数据格式的规范性和一致性。