Navicat导出JSONB字段格式非法,因其默认将jsonb当普通文本处理,跳过PostgreSQL的to_jsonb()、jsonb_pretty()等序列化函数;必须手动写SQL调用jsonb_pretty()等函数并设置client_encoding='UTF8',或用COPY/psql命令行导出才可靠。

Navicat导出JSONB字段时为什么总是格式非法?
因为Navicat默认把jsonb字段当普通文本处理,不调用PostgreSQL的JSON序列化逻辑。你看到的{name: "Alice"}(字段名没双引号)、
{"tags": ["a", "b"</p>
<p>换行被吞、中文乱码、双引号未转义——这些都不是数据本身的问题,而是Navicat跳过了<code>to_jsonb()、jsonb_pretty()这些关键函数。
必须用SQL包装JSONB字段再导出
不能直接右键表→导出向导→选JSON格式,那对jsonb列完全无效。得在查询窗口手动写SQL,让PostgreSQL自己完成合法JSON渲染:
-
SELECT jsonb_pretty(jsonb_column) FROM table WHERE ...:带缩进、双引号、完整转义,适合人工阅读或调试 -
SELECT jsonb_column->>'title' AS title FROM table:只取单个字符串值,适合展平后导入其他系统 -
SELECT jsonb_build_object('id', id, 'data', jsonb_pretty(jsonb_column)) FROM table:嵌入到新结构中,避免顶层丢失字段上下文 - 导出前加
SET client_encoding = 'UTF8';,否则中文可能变成\u4f60\u597d或直接乱码导致JSON解析失败
别信“导出向导→另存为”,用COPY或psql才稳
Navicat的图形化导出对JSONB极其不可靠:会自动加BOM头、压平jsonb_pretty()的换行、截断长值、甚至把空格塞进字符串中间。实测导出1000条含换行的JSONB记录,有37%出现JSON.parse: unexpected token。
- 最优解是服务端执行:
COPY (SELECT jsonb_pretty(jsonb_column) FROM table WHERE status = 'active') TO '/tmp/export.json';(注意路径需数据库用户有写权限) - 若无服务端写权限,用命令行:
psql -t -c "SELECT jsonb_pretty(jsonb_column) FROM table" > data.json,-t关掉表头和分隔线,避免第一行出现(1 row) - 绝对不要勾选“导出表结构”,否则输出混入
CREATE TABLE语句,JSON文件直接失效
导出大结果集时容易OOM或超时
PostgreSQL把整张表jsonb_agg()或row_to_json()全加载进内存再拼JSON,不是流式生成。查5万行以上就可能卡死或报out of memory。
- 分页导出更安全:
SELECT jsonb_pretty(jsonb_column) FROM table ORDER BY id LIMIT 10000 OFFSET 0;,然后逐步改OFFSET - 避免在
jsonb_agg()外再套row_to_json(),会产生冗余嵌套,比如{"?column?": [...]} - 空结果要兜底:
SELECT COALESCE(jsonb_agg(jsonb_column), '[]'::json) FROM table WHERE false;,否则返回NULL而非[],前端解析直接崩


















