← 全部文章

如何校验 JSON:语法与 schema 校验

用 JSON.parse、Python 的 json.loads、jq 或浏览器校验 JSON 语法 —— 并学会用 JSON Schema 检查结构与类型。

校验 JSON 指的是确认一段字符串既在语法上正确(符合 JSON 文法),又(可选地)在结构上正确(与你的应用所期望的形状一致)。本指南讲解如何在 JavaScript、Python、命令行以及浏览器中校验 JSON —— 并解释语法校验与 Schema 校验之间至关重要的区别。

JSON 校验的两种

校验任何东西之前,先想清楚你真正问的是哪个问题:

  • 语法校验 —— 「这到底是不是合法的 JSON?」按 JSON 文法检查引号、逗号、括号与值类型。JSON.parse() 做的就是这件事。
  • Schema 校验 —— 「这份 JSON 是不是带有正确的字段、类型和约束?」会检查 id 是整数、email 必须存在等等。需要 JSON Schema 和 Ajv 之类的校验器。

大多数「validate JSON」的搜索说的就是语法校验 —— 我们从这里开始。

在 JavaScript 中校验 JSON

最简单也最可靠的语法检查就是尝试 parse 并捕获异常。JSON.parse() 在任何无效输入上都会抛出 SyntaxError

function isValidJson(text) {
  try {
    JSON.parse(text);
    return true;
  } catch {
    return false;
  }
}

isValidJson('{"name":"Ada"}');  // true
isValidJson("{'name':'Ada'}");  // false —— 单引号
isValidJson('{"a":1,}');        // false —— 尾随逗号

如果你需要知道字符串为何无效的具体原因,就把错误消息保留下来 —— 里面通常会有出错位置:

function validateJson(text) {
  try {
    return { valid: true, value: JSON.parse(text) };
  } catch (err) {
    return { valid: false, error: err.message };
  }
}

validateJson('{"a":1,}');
// { valid: false, error: "Expected double-quoted property name in JSON at position 7" }

不要用正则表达式校验 JSON。JSON 是递归文法,无法用正则正确校验 —— JSON.parse() 才是规范的校验器,每个 JavaScript 运行时都内建了。

在 Python 中校验 JSON

Python 的 json.loads() 在无效输入上会抛出 json.JSONDecodeError,带有精确的行列号:

import json

def is_valid_json(text):
    try:
        json.loads(text)
        return True
    except json.JSONDecodeError as e:
        print(f"Invalid JSON: {e.msg} at line {e.lineno} column {e.colno}")
        return False

is_valid_json('{"name": "Ada"}')   # True
is_valid_json('{"name": "Ada",}')  # False —— 尾随逗号

在命令行校验 JSON 文件

用 jq

jq 在输入不是合法 JSON 时会以非零状态退出,因此非常适合脚本与 CI:

# 合法时不打印且退出 0;不合法时打印错误并以非零退出
jq empty data.json && echo "valid" || echo "invalid"

用 Python(无需安装)

python3 -m json.tool data.json > /dev/null && echo "valid"

在 CI 流水线中

把仓库里每个 JSON 文件都做一次 pre-commit 或 CI 校验,让畸形的配置永远到不了生产环境:

# 任何 .json 不合法时让构建失败
find . -name '*.json' -not -path './node_modules/*' \
  -exec sh -c 'jq empty "$1" || exit 255' _ {} \;

在浏览器中校验 JSON

若想快速一查、不写代码,把 JSON 贴进 fixjson 的 JSON 校验器。它会随着你的输入即时报告语法错误的精确行列位置,并完全本地运行 —— 不会有数据发送到服务器,因此面对敏感负载也安全。如果 JSON 已经损坏,你想直接修而不是只标记问题,JSON Fix 会自动纠正常见错误。

不只语法:用 JSON Schema 校验结构

语法上合法的 JSON 对你的应用来说仍可能是错的 —— 必填字段缺失、本该是数字的地方是字符串、数值越界。要强制结构,请用 JSON Schema 描述期望的形状,然后用 Ajv(JavaScript)或 jsonschema 库(Python)来校验:

import Ajv from 'ajv';

const ajv = new Ajv();
const validate = ajv.compile({
  type: 'object',
  required: ['id', 'email'],
  properties: {
    id:    { type: 'integer' },
    email: { type: 'string' },
  },
});

validate({ id: 42, email: 'a@b.com' }); // true
validate({ id: '42' });                 // false —— 类型错且缺 email
// validate.errors 包含详细原因

命令行 Schema 校验

在 CI 里对照 schema 校验 JSON,两个 CLI 足以覆盖大多数需求:

# Python —— 装一次即可
pip install jsonschema
jsonschema --instance data.json schema.json && echo OK

# Node —— Ajv 的 CLI
npm i -g ajv-cli ajv-formats
ajv validate -c ajv-formats -s schema.json -d "data.*.json"

每次提交都校验 JSON(pre-commit 钩子)

要彻底阻止未校验的 JSON 被提交,请用 husky + lint-staged 配置一个钩子:

// package.json
{
  "lint-staged": {
    "*.json": [
      "jq empty",                                  // 语法检查
      "ajv validate -s schemas/$name.schema.json -d"
    ]
  }
}

# 安装钩子
npx husky add .husky/pre-commit "npx lint-staged"

对 Python 项目,官方的 pre-commit 框架内建了一个 check-json 钩子,会对每个暂存文件运行 json.loads

常见 JSON 校验错误

校验失败时,原因几乎总在这些之中 —— 每一条都有专门的指南:

常见问题

怎么检查一段字符串是不是合法 JSON?

try/catch 里把它传给 JSON.parse()(JavaScript),或者在 try/except 里传给 json.loads()(Python)。没抛异常就合法。若想免代码地检查,用 浏览器校验器

能用正则校验 JSON 吗?

不能。JSON 是递归文法,正则无法正确表达。请始终使用真正的解析器,例如 JSON.parse()

校验和解析 JSON 有什么区别?

解析把文本变成可用的值;校验只是确认它能够被解析。实践中一次成功的 parse 就是校验 —— 它们是同一个操作,只是当你只关心合法与否时把结果丢掉。

怎样对照 schema 校验 JSON?

JSON Schema,配合 Ajv(JavaScript)或 jsonschema 库(Python)。Schema 校验检查类型、必填字段与约束 —— 而不仅仅是语法。

立刻校验 JSON —— 无需配置

把 JSON 贴进 JSON 校验器,即可看到即时的语法错误及精确的行列位置。全程运行在浏览器中,数据不离开你的机器。