V8 Node v24.15.0, V8 13.6.233.17에서 파서를 실행해 확인했습니다.
Unexpected non-whitespace character after JSON at position N (line L column C)
JSON 문서는 최상위 값을 정확히 하나만 담습니다. 파서가 완결된 값을 하나 읽고 나서 그 뒤에 다른 것을 발견했습니다. 보고되는 위치는 남는 내용이 시작되는 자리이고, 보통은 두 번째 레코드의 시작입니다.
JSON을 붙여넣고 어디서 깨지는지 정확히 확인하기
입력
붙여 넣은 것은 여러분의 브라우저를 떠나지 않습니다. connect-src 허용 목록 덕분에 이는 약속이 아니라 브라우저가 강제하는 보장입니다. 직접 확인하기
실제 원인
어느 쪽이 답인 경우가 많은지, 그 순서대로 정리했습니다.
-
01 입력이 NDJSON이나 JSON Lines
한 줄에 완결된 JSON 값 하나씩, 쉼표도 없고 감싸는 배열도 없습니다. 로그 파이프라인, BigQuery 내보내기, Elasticsearch bulk 작업, 스트리밍 LLM API가 쓰는 형식입니다. 깨진 JSON이 아니라, 줄 단위로 읽어야 하는 다른 형식입니다.
깨지는 예
{"event":"login"} {"event":"logout"}되는 예
const records = text .split('\n') .filter((line) => line.trim()) .map((line) => JSON.parse(line)); -
02 응답 두 개가 이어붙음
대체하지 않고 덧붙여 버린 재시도, 또는 두 청크를 구분 없이 이어 붙인 스트림 읽기.
-
03 디버그 출력이 본문에 딸려 감
지우지 않은 print, 출력된 경고, JSON 뒤에 쓰인 프로파일링 결과 같은 것들입니다. 문서는 여분의 텍스트가 시작되는 지점 직전까지 완벽하게 파싱되고, 위치가 가리키는 곳이 정확히 거기입니다.
-
04 값이 이중으로 인코딩됨
JSON을 담은 JSON 문자열을 한 겹 덜 벗겼거나 한 겹 더 벗긴 경우입니다. 저희 언이스케이프 도구는 값이 몇 겹으로 인코딩되었는지 감지합니다.
다른 런타임에서의 같은 실수
밑바탕의 문제는 똑같고, 다른 건 문구뿐입니다. 동료가 이 중 하나를 들고 왔다면, 그 사람이 보고 있는 건 여러분이 보는 것과 같습니다.
| Python | Extra data: line 2 column 1 (char 8) |
|---|---|
| Firefox | JSON.parse: unexpected non-whitespace character after JSON data |
자주 묻는 질문
- 제 파일이 NDJSON인지 어떻게 알 수 있나요?
- 비어 있지 않은 각 줄이 그 자체로 완결된 JSON으로 파싱되고, 레코드 사이에 쉼표가 없고, 전체를 감싸는 [ ]도 없습니다. 저희 검증기에 붙여 넣으면 그렇다고 알려 주고 레코드를 배열로 묶는 것도 제안합니다.
- 그냥 대괄호로 감싸고 쉼표를 넣으면 안 되나요?
- 됩니다. 작은 파일이면 그게 가장 빠른 해결입니다. 큰 파일이라면 줄 단위로 읽는 쪽이 메모리를 훨씬 덜 쓰고, 그게 바로 이 형식이 존재하는 이유입니다.