使用xitongsys/parquet-go读取嵌套结构Parquet文件遇字段为空问题
解决xitongsys/parquet-go读取嵌套LIST结构体字段为空的问题
针对你遇到的LIST嵌套结构体字段无法读取的问题,核心原因是结构体标签定义不匹配Parquet的LIST结构规范,以及部分类型映射错误,以下是具体修正方案:
修正后的结构体定义
type Play struct { SID string `parquet:"name=si, type=BYTE_ARRAY, convertedtype=UTF8, encoding=PLAIN_DICTIONARY, repetitiontype=OPTIONAL" json:"si,omitempty"` TimeStamp int64 `parquet:"name=ts, type=INT64, repetitiontype=OPTIONAL" json:"ts,omitempty"` SingleID int64 `parquet:"name=sg, type=INT64, repetitiontype=OPTIONAL" json:"sg,omitempty"` PID int64 `parquet:"name=playid, type=INT64, repetitiontype=OPTIONAL" json:"playid,omitempty"` StartTimeStamp string `parquet:"name=startts, type=BYTE_ARRAY, convertedtype=UTF8, repetitiontype=OPTIONAL"` Price []Price1 `parquet:"name=price, type=LIST, repetitiontype=REQUIRED, elementtype=STRUCT" json:"price,omitempty"` } type Price1 struct { CurrID int64 `parquet:"name=currId, type=INT64, repetitiontype=REQUIRED" json:"currId,omitempty"` LPTag string `parquet:"name=lptag, type=BYTE_ARRAY, convertedtype=UTF8, repetitiontype=REQUIRED" json:"lptag,omitempty"` LPrice Money `parquet:"name=lpmoney, type=STRUCT, repetitiontype=REQUIRED" json:"lpmoney,omitempty"` } type Money struct { AdmCurrCode string `parquet:"name=admCC, type=BYTE_ARRAY, convertedtype=UTF8, repetitiontype=OPTIONAL" json:"admCC,omitempty"` AdmCurrValue string `parquet:"name=admCV, type=BYTE_ARRAY, convertedtype=UTF8, repetitiontype=OPTIONAL" json:"admCV,omitempty"` }
关键修正点说明
- 类型匹配修正:将
int改为int64,对应Parquet的INT64类型,避免因类型不兼容导致值解析失败。 - LIST标签补充:给
Price字段添加elementtype=STRUCT,明确告知库LIST的元素是结构体类型,这是解析嵌套LIST的核心配置。 - 字符串类型明确:给所有字符串类型字段补充
convertedtype=UTF8,确保BYTE_ARRAY类型被正确转换为Go字符串。 - 必填/可选标记补全:给
LPrice、AdmCurrValue等字段补全repetitiontype,保证与Parquet文件的Schema约束完全匹配。
额外验证要点
- 确认Parquet文件Schema中的字段名(如
currId、lptag)与结构体标签的name属性大小写完全一致,Parquet字段名区分大小写。 - 检查读取逻辑是否正确绑定结构体,示例读取代码:
file, err := os.Open("target.parquet") if err != nil { log.Fatal(err) } defer file.Close() reader, err := parquet.NewParquetReader(file, new(Play), 4) if err != nil { log.Fatal(err) } defer reader.ReadStop() for reader.Next() { var p Play if err := reader.Read(&p); err != nil { log.Fatal(err) } // 输出验证Price字段 for _, price := range p.Price { fmt.Printf("CurrID: %d, LPTag: %s\n", price.CurrID, price.LPTag) } }
内容的提问来源于stack exchange,提问作者Arv
相关产品推荐
相关产品推荐

