← 全部文章

JSON 数据之后出现非空白字符:修复方法

这个错误意味着一个完整的 JSON 值后面还有多余内容 —— 拼在一起的对象、被当成单块解析的 NDJSON,或末尾的垃圾。如何找出并去掉多余数据。

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}  // 代理服务器追加的调试行
extra

JSON-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。

怎么修 —— 一步步来

  1. 跳到报错位置 —— 从那里开始的所有内容就是「多余数据」。看看紧跟在第一个完整值后面的是什么。
  2. 有多个值? 如果你本来想做一个列表,用 [ … ] 数组把它们包起来,用逗号分隔。
  3. NDJSON / JSON Lines? 按换行切,逐行解析 —— 不要把整个文件一次性解析。
  4. 尾巴上有垃圾? 解析前去掉那些多余字符(分号、重复的 payload、调试输出)。
  5. 在做流式处理? 确认你没有把多条响应拼到一个缓冲区里再解析。

常见问题

「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」 表示数据太少(值被截断了)。

立刻修复