JSON 校验器,免费

实时校验 JSON 语法。获取包含行号的详细错误信息,自动修复常见问题,并立即格式化/压缩 JSON。

等待输入…

JSON 验证:两层、两个不同的问题

一个 JSON 验证器只回答一个二元问题(这是一个格式良好的 JSON 文档吗?)它把输入交给浏览器内部使用的同一个解析器,并报告它是否接受该语法。这个工具只做这件事,仅此而已。它不检查文档里的数据是否表达了你想要表达的意思。第二个问题(文档是否具有你应用所期望的形状、类型与约束?)属于模式 (schema)验证的领域,是像 Ajv(下文会讲)这类工具的地盘。这两项活动相互补充、回答不同的问题;当你需要其中一个却用了另一个,那是范畴错误。一个有用的类比是文字处理器里拼写检查 / 语法检查的区分:拼写(语法)告诉你每个词是不是真词;语法(模式)告诉你句子有没有意义;两者都有用,互不替代,也都不告诉你这篇文章好不好。{"phoneNumber": 12345} 是格式良好的 JSON,但如果你的应用期待 "+1-555-555-1234" 这样的字符串,它就是错的,而一个语法验证器没法告诉你。

在语法检查之外,本工具还提供一个尽力而为的「修复常见问题」一遍处理,会重写开发者意外写出无效 JSON 的四种最常见方式:尾逗号、用单引号包字符串、未加引号的键,以及 undefined 字面量(改写为 null)。它是启发式而非解析器,所以在采用前务必复核修正后的输出。

JSON 简史

JSON 的传记短得出奇。这个缩略词诞生于 State Software, Inc.,一家由 Douglas Crockford 和 Chip Morningstar 在 2001 年 3 月共同创办的小型咨询公司,目的是构建后来被称为 Ajax Web 应用的东西。第一条 JSON 消息于 2001 年 4 月从 Morningstar 位于湾区的车库里的一台电脑发出。Crockford 并不声称发明了 JSON,这个格式已经存在于 JavaScript 语言之中,作为对象字面量的一个子集;他的贡献是把它剥离出来、命名、做了一个网站(json.org 于 2002 年上线,用三种记法描述了该语法并给出了 JavaScript 参考解析器),并为它的采用奔走鼓吹。2005 年 12 月是大多数历史学家把 JSON 写进主流的节点:那个月,Yahoo! 开始用 JSON 提供它的部分 Web 服务。接下来是 IETF:RFC 4627(«The application/json Media Type for JSON»)由 Crockford 本人执笔,于 2006 年 7 月以信息性文档(而非 Standards Track)发布。标准机构在 2013-2014 跟进:2013 年 10 月发布的 ECMA-404 第 1 版(刻意精简(实质内容六页),2014 年 3 月发布的 RFC 7159(放宽了顶层限制,任何 JSON 值)不止于对象和数组,都可以是一份完整文档),以及 2017 年 12 月当前这一对:RFC 8259(现为 Internet Standard STD 90)和与之规范对齐的 ECMA-404 第 2 版。两份文件结对:彼此规范引用并承诺保持一致。也以 ISO/IEC 21778:2017 发表。

用 200 字讲完 JSON 语法

一个 JSON 文档是一个值,前后可有可无地包以空白。共有六种值类型对象,零个或多个名/值对的无序集合,写作 {"k": v, "k2": v2}数组,有序序列,[v, v2, v3](数组按规范保序);字符串,包在双引号里的 Unicode 字符序列(不允许单引号;反斜杠转义 \"\\\/\b\f\n\r\t 以及 \uXXXX;U+0000 到 U+001F 的控制字符必须转义);数字,严格的 ASCII 形式(可选负号、整数部分无前导零、可选小数部分、可选 eE 指数);true / false,JSON 布尔,只能小写;null,表示无值,只能小写。词法单元之间允许空白且会被忽略。没有注释。没有尾逗号。对象的键必须是用双引号括起来的字符串。整套语法一页就写得完。严格的数字形式禁止 hex(0xFF)、八进制(0777)、+ 号、InfinityNaN,以及像 1. 这种尾随小数点;这会逮住任何在「接受更宽松的 ECMAScript 数字形式」的环境里手写 JSON 的人,最常见的就是把十六进制颜色值粘进 JSON 文件的那种情况。

为什么语法这么严,Crockford 的设计选择

两个有意的省略,解释了用户手写 JSON 时大部分的摩擦。不允许注释。JavaScript 同时有 ///* */ 注释;作为 JavaScript 子集的 JSON 两种都没有。Crockford 在 2012 年发于 Google+ 的理由后来被引用过几千次:「我从 JSON 里去掉了注释,因为我看到人们用它来放解析指令,这种做法本来会摧毁互操作性。我知道没有注释让一些人难过,但他们不该难过。」论点是:注释会邀请扩展,如果你的配置里有 // @schema foo.json 而你的工具读取它,那么你的配置文件就不再是 JSON 了。不允许尾逗号。逗号是分隔符,不是终止符。[1, 2, 3] 合法,[1, 2, 3,] 不合法。理由和注释一样:语法简单、跨解析器一致。代价是任何人编辑多行 JSON 对象(加一个属性、调整顺序、删最后一个属性)都要操心逗号。没有 undefinedJavaScript 有 undefined;JSON 没有。用 null 或者干脆把属性省掉。输入里的 BOM。JSON 文档开头的字节序标记(U+FEFF)在传输的 JSON 里是禁止的,但解析器可以选择忽略一个出现的 BOM。在实际中,被老 Windows 编辑器存成「带 BOM 的 UTF-8」的文件会悄无声息地让一些解析器崩溃,也悄无声息地在另一些解析器里正常工作。

常见的 JSON 错误:

JSON Schema,校验「形状」的标准

JSON Schema 是一种基于 JSON 的词汇表,用来描述 JSON 文档的结构与约束。最早的提案由 Kris Zyp 于 2007 年 10 月提交;IETF Internet-Draft 系列以 draft-zyp-json-schema-00(2009 年 12 月 5 日)开始。在接下来的一个半十年里,drafts 接续由半打作者与编辑演进。当前稳定版本是 2020-12 draft(«2020-12» 这个名字指的是它来源的开发快照;实际正式发布是 2022 年 6 月 16 日)。四个最常用的断言关键字承担了多数日常工作:type(把一个值约束为六种 JSON 类型之一,或一组可接受的类型)、required(对象必须包含的属性名列表)、properties(属性名到该属性值的子模式映射),以及 items(应用于数组每个元素的模式)。再配合 minimummaximumminLengthmaxLengthpattern(正则)、format(date-time、email、IPv4 等)和组合关键字(allOfanyOfoneOfnot),JSON Schema 几乎能表达你数据所需的任何「形状」约束。模式本身就是一份 JSON 文档,这种递归性,有人觉得优雅,有人觉得晕。

Ajv,主导地位的 JavaScript 模式验证器

如果你要在 JavaScript 里做模式验证,标准答案是 Evgeny Poberezkin 的 Ajv(Another JSON Schema Validator)。它的窍门是把模式编译成优化过的 JavaScript:运行时不是在模式与数据树上一边走一边查,而是生成一个把每一项检查都硬编码进去的函数,以原生速度运行。这让它在大文档和热验证路径上比朴素验证器快得多。Ajv 支持 JSON Schema drafts 04、06、07、2019-09 与 2020-12;它是 express-validator、AWS API Gateway 的请求验证以及很多主流 Node.js 框架内置的验证器。对应到 Python,标准选择是 Julian Berman 的 jsonschema;对应到 Java,是 Networknt 的 json-schema-validator。要点在于:模式验证是一个已经解决、成熟、工具完备的问题,但你得通过「写出模式」来选择加入。这个工具不替你写模式;它只做语法验证。

JSON5 与 JSONC,宽松的超集

JSON5 是 JSON 的一个正式超集,规范在 json5.org,最初由 Aseem Kishore 于 2012 年设计,现由 Jordan Tucker 维护。它允许严格 JSON 禁止的一切:注释(///* */)、尾逗号、单引号字符串、未加引号的对象键(当它们是合法 ECMAScript 标识符时)、十六进制数字、起始/末尾的小数点(.55.)、Infinity 与 NaN、以及带符号数字。JSON5 文档通常使用 .json5 扩展名,并由像 npm json5 包这样的库解析。JSONC 是微软非正式的「带注释的 JSON」模式,用于 VS Code 的设置文件(settings.jsonlaunch.jsontasks.json)。注释在规范上被允许;尾逗号在参考解析器里被容忍但会给出警告。宽松形式是给「严格 JSON 的纪律会碍事」的人工编辑配置文件用的;机器对机器的数据交换里,严格 JSON 仍然是对的选择。本工具使用浏览器内置的严格 JSON.parse,所以这两种都会被拒,粘贴前请去掉注释和尾逗号,或者先用一个 JSON5/JSONC 解析器把它转成严格 JSON。

面向极大输入的流式验证器

浏览器的 JSON.parse 会把整份文档作为一棵对象树一次性载入内存。对大多数输入这没问题;对日志文件、数 GB 的 API 导出、传感器数据转储就不行。流式做法是把文档作为词法单元流来消费,发出事件(«数组开始»、«字符串值»、«对象键»),过程中永远不持有整个结构。clarinet(Marak Squires)是 Node.js 上的标准流式 JSON 解析器,模仿的是 SAX XML 解析器的范式。Oboe.js(Jim Higson,源自他 2013 年的博士论文)是面向浏览器的对应物,设计用于在 fetch 流入时一边消费 JSON 一边对每个匹配的 JSONPath 发事件;它已经不再活跃维护,但它先驱的技术仍然有用。npm 上的 JSONStream 把 clarinet 包装为对 Node pipe 友好的形态。本页这种纯浏览器工具受可用内存限制;如果你要校验 GB 级 JSON,请在 Node 里跑流式解析器,或在命令行用 jq --stream

现实工作流里 JSON 验证在哪儿重要

配置文件是杠杆最大的场景:tsconfig.jsonpackage.json、ESLint 与 Prettier 的配置、Docker Compose、AWS IAM policies。单一个无效字符就能让 build 挂掉;语法验证器能在 build 之前先把它揪出来。其次是 API 响应:对外部 API 做开发,常常要先盯着一段 payload 问一句「这玩意儿真的是合法 JSON 吗?」再去更深处追 parsing 的 bug。Webhook 负载(Stripe 事件、GitHub Actions 触发、Slack 入站 webhook)是 JSON;快速粘一下、验一下,就能抓住因为签名错乱或杂散字节破坏了 body 的情况。日志条目(Splunk、Datadog、Loki 等结构化日志)是按行的 JSON;一行坏了,整条 ingest 管线都会断。生成的 JSON 文件(lockfiles、build manifest、测试 fixture)在正常开发中有时会以一些嘈杂的方式漂移;语法验证器能抓住生成步骤本身出错的情形。

只做语法验证的诚实边界

一个语法验证器抓不住逻辑错误。它不会告诉你一个「phone number」字段里放的是整数而不是字符串;不会告诉你一个「date」字符串本身是合法字符串但格式不对;不会告诉你一个必需字段缺了;不会告诉你一个本应为正的数字是负的;不会告诉你两个本该一致的字段不一致。这些都属于模式验证的问题。生产系统该走的管线是:(1) 语法验证作为第一道关(这压根能不能当 JSON 解析?(2) 模式验证作为第二道关)它是不是你预期的形状?(3) 业务逻辑验证作为第三道关,这些数据放在其它状态背景下还说得通吗?三层都有工具可用;这个工具只处理第一层。先把 payload 粘进语法验证器的好处是:它把最廉价、最常见的故障模式(杂散的逗号、缺失的大括号)从更昂贵的模式错误中隔离出来,否则后者会把前者淹没。

隐私:为什么「只在浏览器里跑」在这里很重要

在服务器上验证 JSON 需要先把文档上传上去。对寻常公开数据样例,这无害。对包含认证 token、客户 PII、内部员工记录、配置秘密或未发布产品数据的 API 响应,就不无害了。即使是最一丝不苟的删除策略,上传也会落到服务器日志,可能落到 CDN 缓存,可能落到分析管线,可能落到备份里。这个工具在你的浏览器里通过 JavaScript 跑 JSON.parse。粘贴的文档绝不会过网络,点按钮时在 DevTools 的 Network 选项卡里核对,或者载入页面后切到离线(飞行模式)确认验证器仍然能用。可以放心用来验证含密钥的 webhook payload、带认证头的 API 响应、含数据库凭证的配置文件,或任何你不愿被复制到陌生人硬盘上的 JSON。

常见问题

什么是合法的 JSON?

合法的 JSON 必须是以下类型之一:对象({})、数组([])、字符串("")、数字、布尔值(true/false)或 null。所有字符串和对象键都必须使用双引号。数字不能有前导零。元素之间允许存在空白。

「修复常见问题」会做什么?

修复功能会尝试自动纠正常见错误:尾随逗号、将单引号转换为双引号、为未加引号的键加引号、将 undefined 转换为 null。这是一个启发式工具,可能无法修复所有情况 · 请仔细审查结果。

如何在我的应用中校验 JSON?

在 JavaScript 中:使用 JSON.parse() 并捕获错误。在 Node.js 中:fs.readFileSync() + JSON.parse()。在 Python 中:json.loads() 或 json.load()。大多数编程语言都有内置的 JSON 库。

我能验证 JSON5 或 JSONC(带注释的 JSON)吗?

不能直接验。本工具用的是浏览器严格的 JSON.parse,遵循 RFC 8259,注释、尾逗号、单引号、未加引号的键都是语法错误。如果你的输入是 JSON5(json5.org,Aseem Kishore 2012,Jordan Tucker 维护)或 VS Code 的 JSONC,请安装 npm 包 json5jsonc-parser,先转换为严格 JSON 再验证。「修复常见问题」处理了其中一个子集,但它不是完整的 JSON5 / JSONC 解析器。

有大小限制吗?

没有硬性上限,但浏览器的 JSON.parse 会把整份文档作为一棵对象树一次性载入内存。几万行很轻松;几 GB 的日志转储会耗尽内存。要对付特别大的 JSON,请跑流式解析器,比如 clarinet(Marak Squires)或 Oboe.js(Jim Higson,2013),或者在命令行用 jq --stream,它能处理任意大小的文档而不必一次性载入。

我的 JSON 文档会被上传吗?

不会。JSON.parse 在你的浏览器里由 JavaScript 运行。粘贴的文档不过网络,点 Validate 时在 DevTools 的 Network 选项卡里核对,或者加载页面后切到离线,确认工具仍能用。可以放心用来验证含密钥的 webhook payload、带认证头的 API 响应或含数据库凭证的配置文件。

相关工具

免费在线 JSON 格式化器和验证器 JSON → CSV 转换器,免费 JSON → YAML 转换器,免费