如何在Avro架构中定义复杂类型

时间:2016-09-13 12:50:18

标签: python json avro

我已经审阅了avro文档以及在线的几个示例(以及类似的StackOverflow问题)。然后我尝试定义一个avro架构,并且必须逐步退出字段以确定我的问题(来自python中的avro库的错误消息没有人们希望的那样有用)。我有一个JSON文档,我想转换为Avro,我需要为此目的指定一个模式(使用avro-tools从json生成模式不能按预期工作,并在尝试转换时产生AvroTypeException json进入avro)。我使用的是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”字段时,我只看到此错误。

2 个答案:

答案 0 :(得分:2)

Avro的python实现表示联合与其JSON编码不同:它“展开”它们,因此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
}

请注意,null在两种情况下均为unwrapped,这就是your solution无效的原因。

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

答案 1 :(得分:0)

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

{
  "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
  ]
}