Oracle 19c原生JSON字段必须用rs.getObject("col", String.class, SQLType.JSON)读取,且需ojdbc8u3+驱动、AL32UTF8字符集;JSON_OBJECT等表达式返回JSON类型,不可直接映射POJO,须手动解析。
Oracle 19c 中 JSON_OBJECT 生成的 JSON 字段必须用 SQLType.JSON 显式读取
oracle 19c 原生 json 类型字段(如 create table t (j json))在 jdbc 中不会自动转成 string 或 jsonobject,即使你用 rs.getstring("j") 或 rs.getobject("j") 也会抛 sqlexception: invalid column type 或返回乱码。根本原因不是驱动版本低,而是 jdbc 层没注册类型映射。
正确做法是:用带 SQLType 参数的 getObject,且传入 java.sql.SQLType.JSON(注意不是字符串 "JSON"):
String jsonStr = rs.getObject("j", String.class, SQLType.JSON);
- 必须用
ojdbc8u3+(即 21.9+),旧版驱动不识别SQLType.JSON -
rs.getObject("j", String.class)不带第三个参数 → 报错或返回null(即使字段非空) - 服务端字符集必须为
AL32UTF8,否则中文变成??? - 字段允许为
NULL时,getObject(..., String.class, SQLType.JSON)返回null,不是空字符串
Java 里不能直接把 JSON_OBJECT 结果映射到 POJO(Spring JDBC / MyBatis 默认失效)
JSON_OBJECT('name', e.name, 'dept', d.dname) 这类 SQL 表达式返回的是 Oracle 原生 JSON 类型值,不是字符串。Spring 的 BeanPropertyRowMapper、MyBatis 的默认 resultMap 都不认识它,会跳过该列或报 Cannot convert value of type [oracle.sql.JDBCType] to required type。
必须手动介入解析流程:
- 用
JdbcTemplate时,写自定义RowMapper,先调rs.getObject("json_col", String.class, SQLType.JSON)拿字符串,再用 Jackson/Gson 转 POJO - MyBatis 中需注册自定义
TypeHandler(如继承JSONTypeHandler<yourpojo></yourpojo>),并在resultMap里显式指定typeHandler="xxx.JSONTypeHandler" - 别试图让
JSON_OBJECT直接生成 Java 对象——Oracle 不负责反序列化,JDBC 更不负责
JSON_EXISTS 和 JSON_VALUE 可以在 SQL 层过滤/提取,但 Java 端仍要按原规则读取
像 WHERE JSON_EXISTS(j, '$.status') 或 SELECT JSON_VALUE(j, '$.user.id') AS uid FROM t 这类写法,只是让 Oracle 在数据库内做计算,返回结果仍是 JSON 类型(前者是 BOOLEAN,后者是 VARCHAR2 或 CLOB)。关键点在于返回列的类型是否还是原生 JSON:
立即学习“Java免费学习笔记(深入)”;
- 如果
SELECT列是JSON_OBJECT、JSON_ARRAY或未加类型转换的JSON_VALUE(... RETURNING JSON)→ 仍需SQLType.JSON - 如果明确写了
JSON_VALUE(j, '$.id' RETURNING VARCHAR2(100))→ 可用rs.getString()直接读 -
JSON_QUERY默认返回JSON类型,也得走SQLType.JSON流程
别在 PL/SQL 里拼 JSON 字符串来绕过 JDBC 限制
有人试过用 JSON_OBJECT + TO_CHAR 强转成字符串(如 TO_CHAR(JSON_OBJECT(...))),以为能避开类型问题。这看似可行,但有严重隐患:
- Oracle 默认用数据库字符集编码,若非
AL32UTF8,中文直接损坏 -
JSON_OBJECT输出含换行缩进(取决于PRETTY参数),字符串长度不可控,影响网络传输和解析稳定性 - 丢失 JSON 类型语义:后续无法用
JSON_EXISTS等函数再查询该字段 - 不如老老实实升级驱动、配对
SQLType.JSON,这是 Oracle 官方支持的唯一标准路径
真正容易被忽略的是:SQLType.JSON 必须和 String.class 配合使用,传 Object.class 或 JsonObject.class 会失败——JDBC 层只负责吐出合规 JSON 字符串,解析是上层框架的事。


















