Python中JSON转Avro后出现'_'字段的原因咨询
JSON转Avro后出现额外'_'字段的原因及解决办法
问题背景
我尝试使用以下Python代码将JSON转换为Avro格式:
from fastavro import writer, reader, schema from rec_avro import to_rec_avro_destructive, from_rec_avro_destructive, rec_avro_schema avro_objects = (to_rec_avro_destructive(rec) for rec in all_obj[:100]) with open('json_in_avro.avro', 'wb') as f_out: writer(f_out, schema.parse_schema(rec_avro_schema()), avro_objects)
转换过程正常运行,但原JSON结构:
{ 'Date': '2023-07-16', 'Url': 'google.pt', 'Item': {'Title': 'abababab', 'Id': '28e3c5n', 'DedupId': None, 'ImageHash': None, 'Attributes': {'Cost': None, 'Area': None}, 'PropertyDetail': []} }
转换后变成了:
{ 'Date': '2023-07-16', 'Url': 'google.pt', 'Item': {'_': {'Title': 'abababab', 'Id': '28e3c5n', 'DedupId': None, 'ImageHash': None, 'Attributes': {'_': {'Cost': None, 'Area': None}}, 'PropertyDetail': {'_': []}} }
请问这些'_'字段是怎么生成的?
原因分析
你使用的rec_avro库本质是为结构不固定的JSON数据设计的——Avro要求有严格的schema约束,但如果你的JSON记录字段、嵌套结构可能存在差异,rec_avro就会通过带_的包装结构来实现通用兼容。
具体细节:
rec_avro_schema()生成的是通用Avro schema,它用{"name": "_", "type": "record", ...}的结构来包裹任意嵌套的对象、数组或空值。to_rec_avro_destructive函数会递归地将所有嵌套对象、数组都封装到_字段中,这样就能用统一的schema存储结构多变的JSON数据。
解决办法
情况1:JSON结构固定
如果你的JSON结构是固定的,完全不需要依赖rec_avro,直接自定义匹配的Avro schema即可,转换后不会出现额外的_字段。针对你的JSON结构,示例schema如下:
custom_schema = { "type": "record", "name": "MyRecord", "fields": [ {"name": "Date", "type": "string"}, {"name": "Url", "type": "string"}, {"name": "Item", "type": { "type": "record", "name": "Item", "fields": [ {"name": "Title", "type": "string"}, {"name": "Id", "type": "string"}, {"name": "DedupId", "type": ["null", "string"], "default": None}, {"name": "ImageHash", "type": ["null", "string"], "default": None}, {"name": "Attributes", "type": { "type": "record", "name": "Attributes", "fields": [ {"name": "Cost", "type": ["null", "string"], "default": None}, {"name": "Area", "type": ["null", "string"], "default": None} ] }}, {"name": "PropertyDetail", "type": {"type": "array", "items": "null"}, "default": []} ] }} ] }
然后直接用fastavro写入,无需rec_avro的转换函数:
with open('json_in_avro.avro', 'wb') as f_out: writer(f_out, custom_schema, all_obj[:100])
情况2:JSON结构不固定(需要兼容可变结构)
如果确实要处理结构多变的JSON,读取Avro文件时使用from_rec_avro_destructive函数就能还原回原始JSON结构:
with open('json_in_avro.avro', 'rb') as f_in: avro_reader = reader(f_in) original_objects = [from_rec_avro_destructive(record) for record in avro_reader]
内容的提问来源于stack exchange,提问作者Daniel Díaz
相关产品推荐
相关产品推荐

