如何通过Polars将含Dict的列以JSONB格式插入PostgreSQL?
解决Polars写入PostgreSQL时字典列存为JSONB的问题
核心思路
要让Polars把字典列写入PostgreSQL的JSONB类型,需要两步:
- 确保Polars中的列被正确标记为JSON类型(而非普通字符串)
- 显式告诉SQLAlchemy将该列映射为PostgreSQL的JSONB类型
方案一:Polars JSON编码 + SQLAlchemy Schema 指定
这是最稳妥的方式,既避免类型识别错误,又能直接创建JSONB列。
步骤1:处理字典列
用Polars原生的struct.field提取字典(比apply更高效),再用str.json_encode将其转为JSON格式的字符串,同时Polars会将该列标记为JSON类型:
import polars as pl # 提取并处理字典列 df = df.with_columns( pl.col("struct_containing_multiple_info") .struct.field("dict_formatted_column") .str.json_encode() .alias("dict_formatted_column") )
步骤2:定义SQLAlchemy Schema,指定JSONB类型
导入SQLAlchemy的类型,创建对应表的schema,明确将目标列设为JSONB:
from sqlalchemy import JSONB, MetaData, Table, Column # 根据你的实际列类型导入对应类型,比如Integer、String等 metadata = MetaData() target_table = Table( table_name, metadata, # 列出所有列,示例中假设其他列如id为Integer,根据实际情况调整 Column("id", Integer), Column("dict_formatted_column", JSONB), # 添加其他列... schema=schema )
步骤3:写入数据库
调用write_database时传入定义好的schema:
df.write_database( table_name=f"{schema}.{table_name}", connection=postgres_resource.url, engine="sqlalchemy", if_exists="replace", schema=metadata )
方案二:处理ndarray序列化问题(针对含数组的字典)
如果你的字典中包含NumPy数组(之前报错ndarray is not JSON serializable),需要先给psycopg2注册数组适配器,再结合方案一的逻辑:
注册ndarray适配器
import psycopg2 from psycopg2.extras import Json import numpy as np def adapt_ndarray(arr): # 将ndarray转为列表,使其可JSON序列化 return Json(arr.tolist()) psycopg2.extensions.register_adapter(np.ndarray, adapt_ndarray)
之后再执行方案一的列处理和写入步骤即可。
之前错误原因解析
- 使用
json.dumps:生成的是普通字符串,Polars会识别为str类型,PostgreSQL自动创建text列,而非JSONB - 直接用psycopg2适配器:未处理字典中的ndarray,导致序列化失败
- 使用adbc引擎:当前版本对struct类型的 ingestion 支持不完善,暂不推荐
- 不做处理:psycopg2无法直接将Python dict适配为PostgreSQL的JSONB类型,抛出适配错误
内容的提问来源于stack exchange,提问作者Terence Bonin
相关产品推荐
相关产品推荐

