json_object 返回空或报 ora-40442 的主因是传入 null 且未指定 null on null,或含不支持类型(如 long);key 名需双引号包裹;数组须用 json_arrayagg 嵌套;性能瓶颈与版本兼容性需提前规避。

Oracle 19c 的 JSON_OBJECT 能直接拼出合法 JSON,但默认不加引号、不处理 NULL、不支持数组嵌套——用错参数会返回空字符串或报错,不是所有字段都能“直接塞进去”。
为什么 JSON_OBJECT 返回空或报 ORA-40442?
常见原因是传入了 NULL 值且没显式指定 NULL ON NULL 或 ABSENT ON NULL。Oracle 19c 默认行为是 ABSENT ON NULL,即跳过整个键值对;如果所有字段都为 NULL,结果就是空 JSON 对象 {},看起来像“没生成”。更隐蔽的是,若某列类型不支持 JSON 序列化(如 LONG、未命名的嵌套对象),会直接报 ORA-40442: JSON_OBJECT: invalid input value。
- 显式声明
NULL ON NULL才能让 NULL 值输出为"key": null - 避免在
JSON_OBJECT内直接引用LONG、ROWID、未定义别名的子查询结果 - 用
TO_CHAR或CAST预处理日期、数字精度等易出问题的类型
JSON_OBJECT 中 key 名带空格或特殊字符怎么处理?
Oracle 不允许 key 名含空格、连字符或以数字开头——这不是语法限制,而是 SQL 标识符解析规则。如果你写 JSON_OBJECT('first name' VALUE ename),会报 ORA-00904: "first name": invalid identifier。必须用双引号包裹 key 字符串,并确保它是合法的字符串字面量。
- 正确写法:
JSON_OBJECT('"first name"' VALUE ename)(注意外层单引号、内层双引号) - 更安全的做法:用绑定变量或拼接字符串,比如
'"first name"' || ':' || JSON_VALUE(...) - 若 key 来自列值(如动态字段名),必须先用
REPLACE和JSON_ESCAPE处理,否则可能破坏 JSON 结构
如何让 JSON_OBJECT 包含数组(如多个电话号码)?
JSON_OBJECT 本身不接受数组作为 VALUE,它只认标量或子对象。要生成 "phones": ["123", "456"] 这种结构,得靠 JSON_ARRAYAGG 嵌套调用,且要注意聚合上下文和去重逻辑。
- 基本组合:
JSON_OBJECT('phones' VALUE JSON_ARRAYAGG(phone_num)) - 必须搭配
GROUP BY,否则JSON_ARRAYAGG会把全表聚合成一个数组 - 若需去重,加
DISTINCT:JSON_ARRAYAGG(DISTINCT phone_num) - 若数组元素本身是对象(如
{"type":"home","num":"123"}),先用JSON_OBJECT构造每个元素,再交给JSON_ARRAYAGG
性能和兼容性要注意什么?
JSON_OBJECT 是纯 SQL 函数,执行计划里显示为 JSON OBJECT CONSTRUCTOR,但高并发下大量调用仍可能成为瓶颈,尤其当嵌套层级深或字段多时。另外,19c 的 JSON 函数默认输出严格 JSON(双引号、小写 true/false),但某些老客户端解析器对 null 大小写敏感,或对 Unicode 转义不一致。
- 避免在 WHERE 或 JOIN 条件中用
JSON_OBJECT,它无法走索引 - 若需频繁生成相同结构 JSON,考虑建物化视图或提前存为
JSON类型列(JSON CHECK约束) - 跨版本迁移时注意:21c 支持
JSON_OBJECT(ABSENT ON NULL)的简写形式,19c 必须写全
真正麻烦的不是语法,而是当你把 5 层嵌套 + 数组 + 动态 key 全堆进一个 JSON_OBJECT 调用里时,错误信息根本不会告诉你哪一层崩了——得一层层拆开 SELECT 单独验证。











