Javascript is required
踩坑避坑发布于 2026-07-28更新于 2026-08-08审校于 2026-08-085 分钟阅读

SQL 转 JSON:NULL、布尔值与 0/1 的语义差异

SQL 的 NULL 不是字符串,0/1 也不天然等于布尔值。PostgreSQL 有原生 boolean;MySQL 项目中常用 TINYINT(1) 表示开关,但列定义和驱动返回类型仍需确认。本文只讨论 SQL 行转换为 JSON 时的空值和布尔语义,不讨论 INSERT 解析或表结构自动推断。

SQL to JSONNULLBooleanMySQLPostgreSQL

一、问题概述:四种看起来相似的值

SQL NULL 表示缺失/未知,JSON null 是一种明确的 JSON 值,字符串 "null" 是文本,数字 0 是数值。true/false 也不能从任意数据库中的 0/1 自动推导。转换前必须知道列的声明类型和业务含义,而不是只观察一次驱动返回值。

二、最小复现:原生 boolean 与 TINYINT(1) 不是同一声明

PostgreSQL 查询可以直接构造 JSON boolean;MySQL 的 TINYINT(1) 是常见约定,具体返回和 JSON 函数行为要以列定义、服务器版本和驱动为准。

-- PostgreSQL
SELECT json_build_object('enabled', enabled, 'note', note) FROM settings;

-- MySQL
SELECT JSON_OBJECT('enabled', enabled, 'note', note) FROM settings;

-- These are different from the string values '0', '1', and 'null'.

三、根因:NULL 传播和类型转换由数据库与驱动共同决定

SQL 表达式中的 NULL 会参与三值逻辑,比较结果可能是 UNKNOWN;JSON 序列化通常把列的 NULL 表示为 JSON null,但自定义 COALESCE、IFNULL 或驱动转换可能改变它。PostgreSQL 的 boolean 与 MySQL 的数值开关也可能以不同 JavaScript 类型到达应用层。

四、推荐方案:以列契约为准做显式映射

在转换器中为字段记录 dialect、数据库声明类型和允许的输入集合。原生 boolean 只接受 true/false;约定为开关的 TINYINT(1) 才在明确规则下把 0/1 映射为布尔;未知字符串和其他数字应保留或拒绝,而不是静默转换。NULL 统一映射为 JSON null,除非接口契约规定省略字段。

五、完整代码:显式区分两种布尔来源

以下 TypeScript 不猜测驱动行为。调用方必须提供列语义;字符串 "0" 不会被当成数字 0,未知值会抛出错误,避免数据被悄悄改写。

type BooleanSource = "postgres-boolean" | "mysql-tinyint1";

function toJsonBoolean(value: unknown, source: BooleanSource): boolean | null {
  if (value === null) return null;
  if (source === "postgres-boolean" && typeof value === "boolean") return value;
  if (source === "mysql-tinyint1" && (value === 0 || value === 1)) return value === 1;
  throw new TypeError("Value does not match the declared boolean source");
}

console.log(toJsonBoolean(true, "postgres-boolean")); // true
console.log(toJsonBoolean(0, "mysql-tinyint1")); // false
console.log(toJsonBoolean(null, "mysql-tinyint1")); // null
// toJsonBoolean("0", "mysql-tinyint1") throws instead of guessing.

六、常见错误方案

value || false 会把 NULL、空字符串和其他假值全部压成 false;用 Boolean(value) 会让字符串 "false" 变成 true;用 COALESCE(enabled, false) 会丢失 NULL 的业务含义。把每个 0/1 列都转成 boolean 也会误伤计数、状态码和普通整数。

七、边界条件:NULL、字符串和驱动返回类型

区分字段缺失、SQL NULL、JSON null、空字符串和字符串 "null"。某些驱动可能把数值以字符串返回,不能只凭字符串内容转换;应读取列元数据或使用明确查询别名。若接口需要省略 null 字段,应在序列化层显式实现,而不是依赖 JSON.stringify 的偶然行为。

八、如何验证转换结果

在 MySQL 和 PostgreSQL 分别准备 true/false、0/1、NULL、字符串 "0"、字符串 "null" 和普通整数列。检查数据库 JSON 函数输出和驱动行输出,再断言转换器的类型和值。额外验证 null 是 JSON null 还是字段省略,确保与 API 契约一致。

九、FAQ

问:MySQL TINYINT(1) 就是 boolean 吗?答:它常被用作约定,但仍要依据列定义、项目规范和驱动行为确认。

问:NULL 转 JSON 应该变成 false 吗?答:通常应保留为 JSON null,除非业务明确规定缺省值。

问:为什么 Boolean("false") 是 true?答:JavaScript 按非空字符串判断真值,不会解析字符串内容。

十、总结

SQL 到 JSON 的关键是保留语义:NULL、JSON null、字符串 null、0/1 和 boolean 不是同一种值。PostgreSQL 原生 boolean 与 MySQL TINYINT(1) 要分开处理,转换器应依赖列契约、显式映射并拒绝未知值,再用两种数据库的边界样本验证结果。

来源与延伸阅读

技术审校所依据的规范与权威参考资料。

相关文章

继续阅读

可打开关联的浏览器工具,使用自己的样本验证文中的处理流程。

打开关联工具