如何在 Avro Schema 中定义复杂类型

How do I define a complex type in an Avro Schema

我查看了 avro 文档以及几个在线示例(以及类似的 Whosebug 问题)。然后我尝试定义一个 avro 模式,并且不得不逐步退出字段以确定我的问题是什么(来自 python 中的 avro 库的错误消息并不像人们希望的那样有用)。我有一个 JSON 文档,我想将其转换为 Avro,我需要为此目的指定一个模式(使用 avro-tools 从 json 生成模式没有按预期工作并且尝试将 json 转换为 avro 时产生 AvroTypeException)。我正在使用 Avro 版本 1.7.7。这是我要为其定义 avro 架构的 JSON 文档:

{
  "method": "Do_Thing",
  "code": 200,
  "reason": "OK",
  "siteId": {
    "string": "a1283632-121a-4a3f-9560-7b73830f94j8"
  }
}

我能够为非复杂类型定义架构,但不能为复杂的 "siteId" 字段定义架构:

{
  "namespace" : "com.example",
  "name" : "methodEvent",
  "type" :  "record",
  "fields" : [
    {"name": "method", "type": "string"},
    {"name": "code", "type": "int"},
    {"name": "reason", "type": "string"}
    {"name": "siteId", "type": [ "null", "string" ]}
  ]
}

尝试使用之前的架构将 Json 对象转换为 avro 会产生一个 avro.io.AvroTypeException:数据 [参见上面的 JSON 对象] 不是架构 [请参阅上面的 Avro 模式对象]。我只在尝试在模式中定义一个字段来表示上面 json.

中的 "siteId" 字段时才看到此错误

我能够使用以下架构解决问题:

{
  "namespace" : "com.example",
  "name" : "methodEvent",
  "type" :  "record",
  "fields" : [
    {"name": "method", "type": "string"},
    {"name": "code", "type": "int"},
    {"name": "reason", "type": "string"}
    {
      "name": "siteId", 
      "type": {
        "name" : "siteId",
        "type" : "record",
        "fields" : [
          "name" : "string",
          "type" : [ "null", "string" ]
        ]
      }
    },
    "default" : null
  ]
}

Avro 的 python 实现表示联合不同于它们的 JSON 编码:它 "unwraps" 它们,所以 siteId 字段应该只是字符串,没有包装对象。请参阅下面的几个示例。

有效 JSON 编码

非空 siteid:

{
  "method": "Do_Thing",
  "code": 200,
  "reason": "OK",
  "siteId": {
    "string": "a1283632-121a-4a3f-9560-7b73830f94j8"
  }
}

siteid:

{
  "method": "Do_Thing",
  "code": 200,
  "reason": "OK",
  "siteId": null
}

有效 python 个对象(内存中表示)

非空 siteid:

{
  "method": "Do_Thing",
  "code": 200,
  "reason": "OK",
  "siteId": "a1283632-121a-4a3f-9560-7b73830f94j8"
}

siteid:

{
  "method": "Do_Thing",
  "code": 200,
  "reason": "OK",
  "siteId": null
}

请注意,nullunwrapped in both cases which is why 不工作。

不幸的是,python 实现目前没有 JSON decoder/encoder (AFAIK),因此没有简单的方法在两种表示之间进行转换。根据您的 JSON 编码数据的来源,最简单的方法可能是将其编辑为不再包装联合实例。