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

使用asyncpg调用PostgreSQL的jsonb_agg()返回前缀问题排查

解决asyncpg调用PostgreSQL jsonb_agg返回Record对象的问题

你遇到的情况是asyncpg的正常行为:fetch()方法默认返回Record对象的列表,因为你的SQL查询通过jsonb_agg聚合后只返回一行一列的结果,所以result_raw是包含1个Record的列表,需要通过键名提取对应的值。另外你代码里的json.loads()完全多余——asyncpg会自动把PostgreSQL的jsonb类型转换成Python原生的列表/字典对象,不用手动解析JSON字符串。

下面是两种直接获取目标数据的方案:

方案1:改用fetchrow()获取单行结果

既然你的查询只会返回一行数据,用fetchrow()代替fetch()可以直接拿到单个Record对象,再提取字段值就是你需要的列表:

修改fetch_data_from_db()函数:

async def fetch_data_from_db():
    """get data from DB."""
    conn = await asyncpg.connect(DSN)
    result = await conn.fetchrow(QUERY)  # 改用fetchrow()获取单行
    await conn.close()
    return result["jsonb_agg"]  # 直接返回聚合后的Python列表

对应的get_list()和main()可以简化:

async def get_list():
    """Get List"""
    result = await fetch_data_from_db()
    return result

async def main():
    json_result = await get_list()  # 直接拿到原生Python列表

    print(f"type and len of json_result: {type(json_result)}/{len(json_result)}")
    try:
        for persona_data in json_result:
            persona = Person(**persona_data)
            print("Valid JSON object:", persona)
    except ValueError as e:
        print(e)

方案2:在fetch后直接提取目标字段

如果坚持使用fetch(),可以在获取结果后直接提取第一个Record的jsonb_agg值:

修改fetch_data_from_db():

async def fetch_data_from_db():
    """get data from DB."""
    conn = await asyncpg.connect(DSN)
    results = await conn.fetch(QUERY)
    await conn.close()
    return results[0]["jsonb_agg"]  # 直接返回聚合后的列表

这样后续代码无需再做额外处理,get_list()返回的就是原生Python列表。

修改后的输出

运行调整后的代码,会得到如下输出:

type and len of json_result: <class 'list'>/3
Valid JSON object: id=8 name='Donald' surname='Duck'
Valid JSON object: id=9 name='Daisy' surname='Duck'
Valid JSON object: id=10 name='Scrooge' surname='McDuck'

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 17:40:20