如何用Avro定义类似JSON Schema的动态嵌套Map?
如何让Avro Map支持任意层级的嵌套动态结构?
问题背景
在JSON Schema里,我们可以通过patternProperties定义允许任意符合规则键、且值支持任意类型(包括多层嵌套)的对象,示例如下:
{ "description": "Records the raw request and response of an HTTP exchange for debugging purposes.", "type": "object", "definitions": {}, "$schema": "http://json-schema.org/draft-04/schema#", "properties": { "response_json": { "description": "The response body as an optional JSON structure.", "type": "object", "patternProperties": { "^[a-zA-Z0-9_-]+$": {} }, "additionalProperties": false } }, "required": [], "additionalProperties": false }
这种定义可以完美适配如下任意层级嵌套的负载:
{ "response_json": { "foo": "bar", "baz": { "nested": "qux" } } }
{ "response_json": { "moo": "cow", "fish": { "pseudotropheus": { "type": "zebra" } } } }
但在Avro中,直接定义的Map类型只能支持有限层级的嵌套(比如下面的示例仅支持两层),无法达到JSON Schema那样的动态性:
{ "fields": [ { "name": "response_json", "type": { "type": "map", "values": [ "string", { "type": "map", "values": "string" } ] } } ], "name": "sample", "namespace": "foo", "type": "record" }
解决方案:利用Avro递归类型实现无限嵌套
Avro支持递归类型定义,通过创建一个可引用自身的联合类型,就能实现任意层级的嵌套Map。具体实现示例如下:
{ "name": "sample", "namespace": "foo", "type": "record", "fields": [ { "name": "response_json", "type": { "type": "map", "values": { "name": "NestedValue", "type": "union", "members": [ "string", { "type": "map", "values": "NestedValue" } ] } } } ] }
原理说明
这里定义了名为NestedValue的联合类型,它包含两种成员:
- 基础类型
string; - 一个Map类型,而这个Map的值又可以是
NestedValue本身。
通过这种递归引用,Map的值既可以是普通字符串,也可以是另一个Map,而这个嵌套Map的值又能继续是字符串或更深层的Map,以此实现无限层级的嵌套,完全匹配JSON Schema的动态性需求。
扩展支持更多类型
如果需要支持其他基础类型(比如int、boolean、null等),只需将这些类型加入到NestedValue的联合成员中即可:
{ "name": "sample", "namespace": "foo", "type": "record", "fields": [ { "name": "response_json", "type": { "type": "map", "values": { "name": "NestedValue", "type": "union", "members": [ "null", "string", "int", "boolean", { "type": "map", "values": "NestedValue" } ] } } } ] }
关键注意事项
- Avro的递归类型必须指定名称,这样才能在定义内部引用自身;
- 这种方式无需硬编码所有嵌套层级,完全实现了动态嵌套能力;
- 如果数据中存在自定义Record结构,也可以将其加入联合成员,进一步扩展支持的结构类型。
内容的提问来源于stack exchange,提问作者winklebort
相关产品推荐
相关产品推荐

