我建造 Toolz.dev者, 并且在此之前我花了数年时间运送 WordPress 插件和 Laravel API 在所有这一切中,我浪费了最多小时的单一错误消息是 " 428 号位置的 JSON 中的意外令牌的一些变化。" 它几乎什么也告诉你没有行,没有列,它命名的位置经常是几个字符过去了错误的东西,你最终会用手将字符数在一个最小化的 blob 中,或者将整个有效负载粘贴到编辑器中并眯着眼睛。我构建了 JSON 验证器 所以我再也不用这样做了,这就是它所做的事情以及为什么验证 JSON 比看起来更棘手的指南。
TL;博士: JSON验证器根据RFC 8259中的语法检查文本,当文本被破坏时,告诉您第一个错误的确切行,列和字符,用它期望的措辞来表述。它还捕获普通解析器隐藏的东西:重复的键,它们被默默地折叠到最后一个值,它报告有效文档的结构(对象,数组和键计数,嵌套深度和字节大小)。它不是格式化程序。格式化程序假设输入已经有效;验证器是您精确到达的东西,当它不是。
JSON有效是什么意思?
JSON是一种小格式,语法严格,目前的标准是 RFC 8259与其排队 ECMA-404(them)之间,它们恰好定义了一个有效文档可能包含的内容,一个JSON文本是一个单一的值,那个值是一个对象,一个数组,一个字符串,一个数字, true、 false、或者 null.对象用大括号包裹,并保持逗号分隔 "key": value pairs。arrays 包在括号里, 持有逗号分隔的值, 字符串包在双引号里, 从不单引号, 数字遵循一个特定的形状, 没有前导零, 没有尾随小数点, 没有注释, 没有尾随逗号。
最后一句是大多数现实世界 JSON 出现问题的地方,因为很多 JSON 人手写的并不是真正的 JSON。它是一个配置文件 // comments,或者是从javascript源中复制出来的一个对象,其中单个引号和尾随逗号很好,或者是一个手工编辑的夹具,其中有人添加了一个字段并留下了一个悬空的逗号。所有这些都被严格的解析器拒绝,而验证器's的工作就是在特定位置拒绝它们,而不是耸耸肩。
有一点值得澄清,因为它会绊倒多年前学习 JSON 的人:裸值是一个完整、有效的 JSON 文档。 42 JSON 本身是有效的。确实如此 "hello"事实也是如此 true.老的 RFC 4627 要求顶级级别是对象或数组,但该限制在 2014 年被 RFC 7159(后来的 8259)取代时被放弃。如果工具告诉你 42 JSON 是无效的,该工具遵循一个已经过时十多年的规范。
JSON。parse为什么会是一个如此糟糕的错误报告者?
专用验证器赢得一席之地的原因是内置于您语言中的解析器针对快乐的道路进行了优化,而不是为了解释悲伤的道路。 JSON.parse 在浏览器中抛出 a SyntaxError whose消息是引擎特定的,通常给你一个字符偏移,没有行或列。v8说"意外令牌}在json中在位置148。"火狐说"json。parse:意外字符在第1行列149。"safari说了又不一样的话。他们都没有告诉你他们期望什么,位置是从字符串的开始测量的,当你的json有超过几行的时候,这是无用的。
toolz。dev 上的验证器不使用 JSON.parse。它用手写递归下降解析器走文本本身,跟踪行和列,所以当它停止时,它可以把你所有的三个坐标:行,列和绝对字符偏移更重要的是,它知道它中间的语法规则,所以消息是特定的。而不是"意外的令牌,"你得到"在结束大括号之前不允许跟踪逗号,"或"对象键必须是双引号字符串,"或"期望对象成员之后有一个逗号或结束大括号。"那个区别是五秒钟内修复文件和寻找文件之间的区别。
它还在冒犯行上的确切字符下方绘制了一个 caret,就像编译器所做的那样。当您查看配置文件的第 34 行时,"第 12 列"没问题,但是 a ^ 坐在流浪报价的正下方更快。
验证者按名称捕获哪些 JSON 错误?
这些是我最常看到的失败,无论是在我自己的工作中还是在此类工具的支持线程中。验证者会命名每个验证者,而不是报告通用令牌错误。
| 错误 | 它是什么样子 | 为什么它无效 |
|---|---|---|
| 尾随逗号 | {"a": 1,} 或 [1, 2,] |
JSON没有尾随逗号;标准's语法根本不允许在闭包大括号或括号前 |
| 单引号 | {'name': 'Liton'} |
字符串和键必须使用双引号;单引号是 JavaScript 习惯,而不是 JSON |
| 缺少逗号 | {"a": 1 "b": 2} |
第一个之后的每个成员都必须前面有一个逗号 |
| 评论 | {"a": 1} // note |
JSON没有注释语法;的 // 而之后的一切都是意想不到的内容 |
| 未引用的密钥 | {name: "Liton"} |
与 JavaScript 对象文字不同,键是字符串,必须引用 |
| 领先零 | {"n": 007} |
数字可能没有前导零,所以 007 是无效的;写 7 |
| 小数点后跟 | {"n": 5.} |
小数点后的分数至少需要一位数字 |
| 原始控制字符 | 字符串内的字面选项卡或换行符 | 字符串内的控制字符必须转义为 \t、 \n如此类推 |
| NaN 或无限 | {"n": NaN} |
这些在 JavaScript 中有效,但不是 JSON 值 |
| 未终止的字符串 | {"a": "oops} |
没有结束引号的字符串运行到输入的末尾 |
这些中的每一个都会产生一个简单的语言消息和一个位置。前导零情况是一个很好的例子,说明了为什么专用解析器会提供帮助:通用解析器读取 007 为数字 0 然后就过去了 7 作为"额外内容,"指着你 7zai真正的问题是它前面的两个零时,验证者先检查前导-zero模式,直接告诉你。
重复的密钥呢?
这是生产中比任何语法错误都更让我咬伤的一个,因为它根本不是语法错误。这是有效的 JSON:
{
"timeout": 30,
"retries": 3,
"timeout": 60
}
RFC 8259说对象内的名称"应该是唯一的,"但是它不禁止重复,所以需要一个解析器接受这个。接下来发生的事情是麻烦开始的地方:标准说重复名称的行为是不可预测的,实际上几乎每个解析器都保留最后一个值,并默默地丢弃较早的值。所以这个对象解析到 {"timeout": 60, "retries": 3}并且 "timeout": 30 您在文件顶部精心设置的已无预警,如果两个人编辑了配置,或者合并出错,或者模板步骤两次发出相同的密钥,则会出现任何解析器都不会为您标记的错误。
Validator 标记它。Duplicate-key 检测默认打开,并且由于重复项是合法的,因此将其报告为警告而不是错误:文档仍然有效,但您被告知在同一对象中出现不止一次的每个密钥,其行和 a JSON 指针 path,这样你就可以在嵌套结构内部找到它,如果你真的想要重复,你可以关闭检查,大多数时候,看到警告是你意识到出了什么问题的那一刻。
验证器与格式化程序有何不同?
Ren互换使用词语,工具重叠,但回答的问题不同 A. JSON 格式化程序 以你已经相信有效的 JSON 重新打印它并具有一致的缩进,这样人类就可以读取它如果你手里有一个格式化程序损坏的 JSON,它能做的最好的事情就是拒绝一个验证器's 整个目的是损坏的情况:它告诉你在哪里以及为什么。toolz。dev 验证器同时执行这两项工作,因为一旦它确认了文档的有效性,它就已经解析了它,所以它漂亮地打印了结果在同一个通行证中。但标题功能是诊断,而不是缩进。
与邻近的工具也存在同样的关系。 JSON 迷你器 剥离空白以缩小有效负载,这只有在有效输入上才有意义。 JSON 分拣机 重新排序稳定差异的键,同样是在有效输入上。 JSON 逃脱和逃脱 工具处理将 JSON 嵌入字符串中。和 JSONPath 测试器 查询您已经确认的文档已形成良好。验证是所有文档之前的步骤,这就是为什么每当 API 响应或配置文件表现奇怪时,我都会首先运行它。对于这些文档如何组合在一起,有更广泛的介绍 JSON 工具的终极指南。
结构统计告诉您什么?
Document 验证时,工具会报告它的形状:它包含多少个对象和数组,有多少个键,有多少个字符串,数字,布尔值和空值,嵌套有多深,以及它的大小(字符和 UTF-8 字节),这不是装饰,当你收到一个陌生的 API 响应时,深度数字一眼就能告诉你你是处理平记录还是深嵌套树,而密钥计数大致告诉你解析它会有多少工作。
字节数字比人们预期的更重要。请求大小限制、消息队列限制和数据库列限制几乎总是以字节而不是字符来衡量,当您的 JSON 包含 ASCII 之外的任何内容时,两者就会有所不同。表情符号或重音名称在屏幕上是一个字符,但在电线上有两个、三个或四个字节。如果有效负载碰撞到 256 KB 限制,字符数会误导您,字节数不会。验证者计算真正的 UTF-8 字节长度,因此您看到的数字就是限制正在计数的数字。
我如何使用它
My workflow枯燥而快速,这是重点,当集成中断时,我将原始响应体直接从网络选项卡中复制出来,粘贴到验证器中,如果它有效,绿色结果和统计告诉我问题在其他地方,在我的代码中而不是他们的数据中,并且我在两秒钟内排除了整类原因,如果它无效,我将行和列得到,修复它,然后继续。当我手工编辑一个config文件时,我在提交之前粘贴进去,主要是为了抓住我似乎总是留下的尾随逗号和偶尔从复制粘贴中重复的密钥。对于任何组装自己的套件的人,验证器与中的其他要点并排 web开发人员工具包。
隐私角度也不是事后才想到的,最需要验证的JSON正是他们应该最小心使用的JSON:携带令牌的API响应,带有凭据的配置文件,带有客户数据的有效负载验证器所做的一切都发生在你的浏览器中,在JavaScript中,在你的机器上,没有任何东西被上传,记录或存储,你可以通过在验证时打开网络选项卡,或者通过断开与互联网的连接并观看工具继续工作来证明。
常见问题
为什么我的JSON看起来不错就说它无效?
1个最常见的原因是闭包大括号或括号前的尾随逗号,JSON需要双引号的单引号,两个成员之间缺少逗号,或者评论,JSON根本不允许这4个都很容易被眼睛错过,尤其是在一个大文件中,验证者命名了它找到哪一个,并给了你确切的行和列,所以你不是扫描整个文档,而是直接跳到它停下来的字符。
单个数字或字符串本身是否有效 JSON?
是。在RFC 8259下,任何JSON值都是完整的JSON文本,所以 42、 "hello"、 true、和 null all 自己验证,顶级必须是对象或数组的规则来自于较旧的 RFC 4627,于 2014 年被移除,拒绝裸值的工具是遵循过时的规范。
验证者是否更改或上传我的数据?
No。它解析浏览器中的文本,从不发送到任何地方。在有效的文档上,它会产生一个漂亮的打印副本,以方便,但该副本是在本地生成的,并且原始内容从未传输,记录或存储。由于没有服务器往返,该工具也可以在页面加载后断开网络。
JSON 仍然有效,为什么还要关心重复的密钥?
因为重复几乎总是意味着您无意的数据丢失。该标准允许重复的密钥,但它们的处理未定义,并且在实践中解析器仅保留最后一个值并丢弃其余值。因此,配置在哪里 timeout 2次悄然出现丢失第一个设置,验证者会警告你每个重复键及其位置,这通常是你发现错误合并或复制粘贴错误的那一刻。
这可以通过注释(例如 tsconfig 或 VS 代码设置文件)验证 JSON 吗?
No,那是故意的,那些文件是带有注释的JSON(JSONC)或JSON5,它们是放宽规则的单独格式,验证器针对的是严格的RFC 8259,因此它会将注释标记为错误,如果您需要在配置文件中注释,那是一种信号格式,应该是为它构建的东西,例如YAML或TOML,而不是JSON超出标准允许的范围。
JSON 验证和格式化有什么区别?
Validating 检查文本是否服从 JSON 语法,如果不服从,则准确地告诉你它在哪里中断格式化假设文本已经有效,并且仅调整其空白以获得可读性。当出现问题时,您会触及验证器,并且需要知道什么;当一切都很好并且您只希望它可读时,您会触及格式化器。该工具两者兼而有之,但其存在的理由是诊断。
我可以验证多大的文件?
Comfortably 进入几十兆字节,只受你的浏览器's内存的限制,因为整个文档在你的设备上一次性解析,没有上传大小上限,因为没有上传对于一个真正巨大的文件,在千兆字节中,流命令行验证器是更好的仪器,因为浏览器一次性将整个文本保存在内存中。



