You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 08:25:55