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

如何用PyArrow read_json()将结构体列表解析为StructArray

问题描述

我能成功用pyarrow的read_json方法读取金融交易JSON数据为Table,JSON里包含asks和bids两个结构体列表。

当前使用的代码:

schema = pa.schema([('time', pa.timestamp(unit='ns', tz='UTC'))])

parse_options = pj.ParseOptions(explicit_schema=schema)

table = pj.read_json(file, parse_options=parse_options)

执行后Table的结构如下:

pyarrow.Table
time: timestamp[ns, tz=UTC]
instrument: string
asks: list<item: struct<price: string, liquidity: int64>>
  child 0, item: struct<price: string, liquidity: int64>
      child 0, price: string
      child 1, liquidity: int64
bids: list<item: struct<price: string, liquidity: int64>>
  child 0, item: struct<price: string, liquidity: int64>
      child 0, price: string
      child 1, liquidity: int64
ask_prices: list<item: struct<price: string, liquidity: int64>>
  child 0, item: struct<price: string, liquidity: int64>
      child 0, price: string
      child 1, liquidity: int64

查看首行的asks或bids字段时,它们是ListArray类型。我希望将这些数据处理为StructArray以便使用field()方法,尝试在schema中指定StructArray但没成功,求可行解决方案。

示例JSON行:

{"type": "PRICE", "time": "2022-01-04T15:55:12.710818633Z", "bids": [{"price": "1.13134", "liquidity": 1000000}, {"price": "1.13133", "liquidity": 2000000}, {"price": "1.13132", "liquidity": 2000000}, {"price": "1.13130", "liquidity": 5000000}], "asks": [{"price": "1.13145", "liquidity": 1000000}, {"price": "1.13147", "liquidity": 2000000}, {"price": "1.13148", "liquidity": 2000000}, {"price": "1.13149", "liquidity": 5000000}], "closeoutBid": "1.13130", "closeoutAsk": "1.13149", "status": "tradeable", "tradeable": true, "instrument": "EUR_USD"}
解决方案

首先明确:你的JSON里asks和bids本身是数组(列表),所以在Arrow中对应的类型必然是list<struct<...>>(ListArray包裹StructArray),无法直接读取为纯StructArray——除非JSON字段本身是单个结构体而非数组。不过可以通过后续转换实现需求,具体如下:

1. 直接访问嵌套结构体字段

不需要转换类型,直接通过ListArray的嵌套语法即可访问结构体里的字段:

# 提取所有asks列表中每个结构体的price字段
ask_prices = table['asks'].flatten()['price']

# 访问第一行asks列表里的第一个结构体的liquidity字段
first_ask_liquidity = table['asks'][0][0]['liquidity']

# 用Arrow计算工具批量处理
import pyarrow.compute as pc
# 取每个asks列表中第一个元素的price
first_ask_prices = pc.list_element(table['asks'], 0)['price']

2. 展开ListArray为StructArray(多行)

如果需要把每个结构体单独拆成一行,可以用explode方法,此时展开后的字段就是StructArray:

# 展开asks字段,每个结构体对应一行新数据
exploded_table = table.explode('asks')
# 此时exploded_table的asks字段类型为struct<price: string, liquidity: int64>
print(exploded_table['asks'].type)
# 直接用field方法访问结构体字段
exploded_table['asks'].field('price')

3. 读取时指定完整嵌套Schema

如果想在读取阶段就明确指定所有字段的类型(包括嵌套结构),可以定义完整的Schema:

import pyarrow as pa
import pyarrow.json as pj

# 先定义单个订单的结构体类型
order_struct = pa.struct([
    ('price', pa.string()),
    ('liquidity', pa.int64())
])

# 定义完整的Table Schema
schema = pa.schema([
    ('time', pa.timestamp(unit='ns', tz='UTC')),
    ('instrument', pa.string()),
    ('asks', pa.list_(order_struct)),
    ('bids', pa.list_(order_struct)),
    ('type', pa.string()),
    ('closeoutBid', pa.string()),
    ('closeoutAsk', pa.string()),
    ('status', pa.string()),
    ('tradeable', pa.bool_())
])

parse_options = pj.ParseOptions(explicit_schema=schema)
table = pj.read_json(file, parse_options=parse_options)

这样读取后的asks和bids依然是ListArray,但结构完全符合预期,后续处理更顺畅。

内容的提问来源于stack exchange,提问作者John Duffy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 10:15:13