SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data 表示解析器成功读到了一个完整的 JSON 值 —— 然后在它后面又发现了更多非空白内容。JSON 顶层只允许一个值,所以它后面跟着的任何东西都是错误。下面讲讲「多余数据」是怎么来的以及怎么修。
错误长什么样
// Firefox
SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data
at line 1 column 18 of the JSON data
// V8 (Chrome / Node / Edge)
SyntaxError: Unexpected non-whitespace character after JSON at position 17
SyntaxError: Unexpected token { in JSON at position 17 // 老一点的措辞
// Python(类比)
json.decoder.JSONDecodeError: Extra data: line 1 column 18 (char 17)报的位置指向有效值之后的第一个字符 —— 「多余数据」就是从那里开始的。
为什么会这样
原因 1 —— 两个 JSON 值拼在一起
// ❌ 两个对象首尾相接 —— 一个有效值,然后还有更多
{"id":1}{"id":2}
// ^ 第 8 个位置:JSON 数据后出现了非空白
// ✅ 用数组包起来
[{"id":1},{"id":2}]原因 2 —— NDJSON / JSON Lines 被当成一团解析
日志文件和流式 API 经常 会发出一行一个 JSON 对象(NDJSON)。JSON.parse() 只读第一行的值,遇到下一行就栽了。
// ❌ 对整个文件做 JSON.parse
{"event":"login"}
{"event":"logout"}
// ✅ 一行一行解析
const rows = text
.split('\n')
.filter(Boolean)
.map((line) => JSON.parse(line));原因 3 —— 尾巴上的垃圾或者重复的响应
// ❌ 多余文字、被复制了一遍的 payload、或末尾的分号
{"ok":true};
{"ok":true} // 代理服务器追加的调试行
extraJSON-RPC 和其他带分帧的流
如果你正在消费一个协议 —— stdio 上的 JSON-RPC、Language Server Protocol (LSP)、Debug Adapter Protocol —— 多个 JSON 消息按设计就是流过同一个通道的。它们各自带了一层分帧层,告诉你下一条消息有多长,正是为了让你不至于在一个缓冲区里去解析两个值:
Content-Length: 87\r\n
\r\n
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}Content-Length: 42\r\n
\r\n
{"jsonrpc":"2.0","id":1,"result":{...}} 规则是:读 Content-Length 头,然后读正好那么多字节,然后解析一个 JSON 值,然后循环。如果你把整个通道一口吞掉再一次解析,就会撞上「unexpected non-whitespace character after JSON data」,因为里面有很多个值。
对 NDJSON 来说,对应的规则是「按 \n 切,然后逐行解析」。共通的主题是:一串 JSON 消息总得有一层分帧;裸拼接不是合法的 JSON。
怎么修 —— 一步步来
- 跳到报错位置 —— 从那里开始的所有内容就是「多余数据」。看看紧跟在第一个完整值后面的是什么。
- 有多个值? 如果你本来想做一个列表,用
[ … ]数组把它们包起来,用逗号分隔。 - NDJSON / JSON Lines? 按换行切,逐行解析 —— 不要把整个文件一次性解析。
- 尾巴上有垃圾? 解析前去掉那些多余字符(分号、重复的 payload、调试输出)。
- 在做流式处理? 确认你没有把多条响应拼到一个缓冲区里再解析。
常见问题
「unexpected non-whitespace character after JSON data」是什么意思?
解析器读到了一个有效的 JSON 值,然后在它后面发现了更多内容。JSON 只允许一个顶层值,所以后面跟着的那些字符是非法的。
怎么解析多个 JSON 对象?
如果是拼在一起的,用数组包起来。如果是一行一个(NDJSON / JSON Lines),按换行切再单独 JSON.parse() 每一行。
这和「Unexpected end of JSON input」是同一回事吗?
它们是反义。这个错误表示数据太多(完整值后面还有东西);「Unexpected end of JSON input」 表示数据太少(值被截断了)。
立刻修复
- JSON Fix —— 在浏览器里找出末尾的多余数据并清掉
- Unexpected End of JSON Input —— 相反的「数据太少」错误
- 如何修复 JSON.parse 的 Unexpected Token 错误 —— 每一种 token 变体
- 修复「[object Object] is not valid JSON」 —— 完整的语法错误参考