JSON tool
Six operations — format, minify, validate with location, sort keys, escape and convert to CSV — share one input, so a change anywhere can be replayed
// 与 /* */)、单引号字符串、尾随逗号、NaN / Infinity、以及未加引号的对象键——这些都是 JSON5 或 JavaScript 对象的写法,不是 JSON 标准的一部分,解析器拒绝它们是正确行为。本页不提供"宽松模式":把非法输入偷偷"修好"会让你以为数据入库时也会通过,风险比报错大得多。
Input
粘贴 JSON,或点右侧按钮填入示例操作
格式化只做「重新排版」,不会改变值的类型,也不会给键排序——取消勾选「保留键的原始顺序」才会按键名重排(与「键排序」一致)。输出会给出字符数与行数。
Result
JSON 格式化、校验与转 CSV 里最容易踩的几件事
严格 JSON 的语法其实只有几页纸,但报错信息几乎没法读。RFC 8259 定义的 JSON 只有六种结构:对象 { }、数组 [ ]、字符串、数字、布尔值 true / false、以及 null。对象必须是「字符串键 + 冒号 + 值」,键必须用双引号;数组元素之间必须用逗号分隔,且最后一项后面不能再有逗号;字符串里除了少数字符外都不能直接出现控制字符。规范很短,可浏览器和多数语言抛出的错误却只是「Unexpected token } in JSON at position 42」——它只说第 42 个字符处出了意外,不告诉你第 42 个字符在第几行。本页做的就是把那个字符位置换算成「第 X 行第 Y 列」,同时在输入框里选中出错位置,让你一眼看到问题在哪。
尾随逗号、注释、单引号为什么必须报错。这是三个最常见的「看起来没问题」的写法:{ "a": 1, }(尾随逗号)、// 说明 或 /* 说明 */(注释)、{ 'a': 1 }(单引号)。它们全都是 JSON5 或 JavaScript 对象字面量的扩展,不是 JSON。JSON 的设计目标之一是「用极小的解析器就能正确读出」,因此它刻意不允许这些方便写法:注释会让同一份数据在没有注释语法的解析器里直接失败,尾随逗号会让「按逗号切分再逐段解析」的流式解析器多出一个空段。更麻烦的是,很多 JavaScript 环境(包括浏览器控制台、eval、以及 JavaScript 配置文件)会接受它们,于是同一段文本在本地「没问题」、发到服务端或换个语言解析时就炸。本页站在严格 JSON 这一边:宁可现在报错,也不要让它到生产环境才暴露。同样地,NaN 与 Infinity 在 JSON 里也不是合法值——需要表达「非数」时请用 null 或字符串。
格式化与压缩各自解决什么问题。格式化(缩进 2 空格 / 4 空格 / Tab)是为了给人看:代码评审、配置比对、排查层级关系。这里有一个容易被忽略的细节——格式化不应该改变键的顺序。有些工具会顺手把键按字母排序,看起来整齐,但「字段顺序」在不少场景下是有意义的(日志字段的自然阅读顺序、接口文档的示例顺序、以及对比两份文件的差异),悄悄重排会让 diff 噪点暴增。本页默认保留原始顺序,需要排序时请显式点「键排序」。压缩(minify)则是为了给机器传:去掉缩进与换行后体积通常能小两三成,放进请求体、环境变量或配置文件里更省事。注意压缩只删「结构上的空白」,字符串内部的空格与换行会被完整保留,所以压缩后解析出来的数据与压缩前完全等价。
转 CSV 的坑几乎全在「值里有逗号、引号、换行」和「编码」上。CSV 看起来很土,但它有一个所有表格软件都认的正式规范 RFC 4180。规范里真正的难点只有一条:当某个单元格里出现逗号、双引号或换行时,必须用双引号把整格包起来,并把格内的每个双引号写成两个。少了这一步,一个地址里的逗号就会把整行拆歪;多写一层引号又会多出真实的引号字符。另外三件事同样常见:① 表头要取所有对象的键的并集(接口返回的数组里,元素往往不是每个都有全部字段),缺字段的位置留空而不是错位;② Excel 在简体中文 Windows 上双击打开无 BOM 的 CSV 时会按本地代码页解读,中文直接乱码,因此本页默认在文件开头写入 UTF-8 BOM;③ 数字与文本的界线——CSV 没有类型,007 与 7 到了表格里都会被当数字,需要保留前导零时得在导出前把它变成带引号的文本。本页严格按 RFC 4180 处理这三类字符,嵌套对象与数组会写成一格紧凑 JSON,而不是被压平成多列(压平会丢失结构与层级信息,宁可让你再处理一次)。
为什么不上传到服务器。JSON 是最容易夹带敏感内容的格式:接口返回里可能有 token、数据库配置、内网地址、用户的手机号与身份证号,运维配置文件里往往还有密钥。把这样一段文本粘进一个在线格式化工具,如果它在服务端解析,你就等于把凭证复制了一份给第三方——而且很多站点的"历史记录"会把它留在数据库里。本工具的全部逻辑(解析、定位、排序、转义、转 CSV)都是运行在你浏览器内的一段纯 JavaScript 函数,写在页面的 PURE 区块里,可以用开发者工具的 Sources 面板逐行读完;整页没有任何提交请求,也没有写入 localStorage 或 cookie 的历史记录。断网状态下刷新页面,它照样能用。
FAQ
position is a character offset counted from character 0 (in V8 it counts UTF-16 code units: Chinese and full-width punctuation count as 1, emoji and other supplementary-plane characters count as 2) - it is not a line number. This page converts it into line and column and shows a short context, e.g. 'near line 3, column 15: "age": ,'. It also selects that spot in the input box and scrolls to it. If some browser's error message carries no position, this page honestly says 'cannot locate it, but this is not valid JSON' - it will never invent a position for you.
Because those tools use permissive parsing (JSON5, JSONC, or straight eval). They are convenient, but the result is that the same text fails in Python's json.loads, Java's Jackson and Go's encoding/json - database writes, gateway forwarding and message-queue consumers all break at that moment. This page sticks to strict RFC 8259 so you discover the problem at the moment you paste, not after you ship. By the way: VS Code's settings.json and TypeScript's tsconfig.json allow comments because they read JSONC (JSON with Comments), not standard JSON.
It depends on whether your input was already beyond JavaScript's precision limit. JSON.parse resolves numbers to IEEE 754 double-precision floats, so integers above 2 to the 53rd (certain snowflake IDs, 19-digit order numbers, for instance) are already distorted at the moment of parsing - formatting them afterwards is distorted too, and this page cannot recover them either. For those cases, have your API return IDs as strings. Also, formatting and minifying only re-lay out the text: they will not turn 1.0 into anything other than 1, and they do not change key order (unless you explicitly click 'sort keys').
CSV is a two-dimensional table - one row per record - so it needs 'a set of records with the same shape'. When the top level is an object (say { "total": 3, "rows": [ ... ] }), this page clearly says it is not supported rather than deciding on its own which field you meant to export - if it guessed wrong, you might never notice. The right move is to take out the array you want and paste that. Likewise, arrays mixing numbers or strings, or whose elements are not objects at all, are refused with the reason explained.
That is Excel's automatic type inference, not a flaw in the CSV itself: an 18-digit number becomes 1.2E+17, and text like 2024-01-05 gets read as a date. The CSV specification has no concept of 'type', so no tool can stop Excel from doing this. The dependable fix: for long numbers that must stay exact (order numbers, ID numbers), after export set that column to Text in Excel and re-import (or use Data - From Text/CSV and mark the column as Text in the import wizard). The UTF-8 BOM this page adds by default only fixes Chinese mojibake - it does nothing for type inference.