我已经审阅了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”字段时,我只看到此错误。
答案 0 :(得分:2)
Avro的python实现表示联合与其JSON编码不同:它“展开”它们,因此siteId
字段应该只是字符串,没有包装对象。请参阅下面的几个例子。
非空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
}
非空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
]
}