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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 02:13:20