SQLite json_extract 的返回类型:只取一个字段是数字,多加一条路径为什么变成文本
某段查询原本只取 quantity,应用收到数字 7;后来为了顺便取 label,给 json_extract 增加一条路径,返回值却成了文本。SQLite 的这个函数并不固定返回一种“JSON对象”:路径个数与被取出的值类型,都会影响最终的SQL结果。
以下完整程序在 Node.js v24.19.0、其内置 SQLite 3.53.3 上运行,需要提供 node:sqlite 模块的 Node.js 版本。建议使用相同版本或兼容的 Node.js 24 环境。保存为 demo.mjs,运行 node --no-warnings demo.mjs;该参数只让示例输出不夹带模块状态警告。数据库是 :memory:,不创建磁盘数据库,也不需要安装npm依赖。
AI模型生成概念示意:文档中的单个图形直接取出,多项图形则一起放入封套;它表示标量与集合文本的区别,不是SQL执行截图。
完整实验
import { DatabaseSync } from 'node:sqlite';
const db = new DatabaseSync(':memory:');
try {
const document = '{"quantity":7,"label":"lamp","note":null}';
const row = db.prepare(`
SELECT
json_extract(?, '$.quantity') AS single_value,
typeof(json_extract(?, '$.quantity')) AS single_type,
json_extract(?, '$.quantity', '$.label') AS pair_value,
typeof(json_extract(?, '$.quantity', '$.label')) AS pair_type
`).get(document, document, document, document);
console.log('values', JSON.stringify(row));
const states = db.prepare(`
SELECT
json_extract(?, '$.note') AS explicit_null,
json_extract(?, '$.missing') AS missing,
json_type(?, '$.note') AS explicit_type,
json_type(?, '$.missing') AS missing_type
`).get(document, document, document, document);
console.log('states', JSON.stringify(states));
const text = db.prepare(`
SELECT json_extract(?, '$.label') AS value
`).get(document).value;
console.log('text-value', text);
try {
JSON.parse(text);
} catch (error) {
console.log('parse-scalar', error.name);
}
console.log('parse-pair', JSON.stringify(JSON.parse(row.pair_value)));
} finally {
db.close();
}本地实际输出
values {"single_value":7,"single_type":"integer","pair_value":"[7,\"lamp\"]","pair_type":"text"}
states {"explicit_null":null,"missing":null,"explicit_type":"null","missing_type":null}
text-value lamp
parse-scalar SyntaxError
parse-pair [7,"lamp"]single_value 是数字 7,single_type 是 integer。只取一个路径且值为JSON数字时,SQLite 返回SQL数字;若该路径指向JSON字符串,则返回已经去掉JSON外层引号的文本。pair_value 是内容为 [7,"lamp"] 的SQL文本,pair_type 为 text,因为多个路径的结果会被装进一个JSON数组。
程序用 JSON.stringify 展示数据库返回的行,因此 pair_value 里的双引号在终端会显示转义符。这是外层展示格式,不表示SQLite额外给字段内容插入了反斜杠。判断数据库类型应看 typeof 的结果,而不是只凭控制台里看到了几层引号。
states 中的 explicit_null 与 missing 都是SQL NULL,进入JavaScript后都显示为 null。要区分原文明确写了JSON null,还是根本没有该路径,可以同时调用 json_type:前者返回文本 "null",后者返回SQL NULL。业务若把“主动清空”和“未提供”视为两种状态,就不能只保留 json_extract 的一个结果。
边界与使用约定
parse-scalar 的 SyntaxError 是故意验证错误用法:单个 label 已被取成普通文本 lamp,不能再把它当成完整JSON文本解析。相反,pair_value 仍是一段JSON数组文本,JSON.parse 后得到数组 [7,"lamp"]。调用方应按约定的返回结构消费,不要给所有查询结果统一套一次 JSON.parse。
单路径指向数组或对象时,返回的仍然是它们的JSON文本表示,因此“单路径一定是数字”同样错误。可在接口层约定字段允许的JSON类型,再用 json_type 做检查;需要数字运算的字段,不应靠强制转换把不合格文字变成看似可用的数值。
无效JSON或不合法的路径可能导致查询报错,路径不存在则属于本文展示的正常空结果。把这两类情况分开记录,才能区分输入损坏和业务上尚未填写。此处参数绑定保护的是传入数据的SQL边界,不会自动证明JSON结构符合你的业务要求。
参考资料
官方资料核验日期:2026-10-02。


