mygems

잘못된 JSON 고치기: 흔한 오류 총정리

Unexpected token, 마지막 쉼표, 작은따옴표, 허용되지 않는 주석. JSON 오류의 의미와 줄 위치를 찾아 고치는 방법을 설명합니다.

작성: mygems ·

JSON은 규칙을 알기 전까지는 쓸데없이 까다롭게 느껴질 만큼 엄격합니다. 마지막 쉼표는 안 됩니다. 큰따옴표만 씁니다. 주석은 없습니다. 키는 반드시 따옴표로 감싸야 합니다. 이 중 하나라도 어기면 문서 전체가 거부되고, 문자 위치만 알려 줄 뿐 무엇이 잘못됐는지는 거의 말해 주지 않는 메시지가 나옵니다.

이 글은 오류 메시지를 원인에, 원인을 해결 방법에 연결해 설명합니다.

빠른 답

  1. 위치를 찾습니다. 모든 파서는 줄과 열, 또는 문자 오프셋을 알려 줍니다. 그곳으로 가세요. 실수는 그 지점이나 바로 앞에 있습니다.
  2. 흔한 다섯 가지를 확인합니다. 마지막 쉼표, 작은따옴표, 따옴표 없는 키, 주석, 항목 사이의 빠진 쉼표입니다.
  3. 오류가 위치 0 또는 1행 1열이라면 JSON 자체가 문제가 아닙니다. HTML 오류 페이지, 빈 응답, 바이트 순서 표시(BOM) 같은 다른 것을 받은 것입니다.

어떤 컴퓨터에서든 정확한 위치를 확인하는 방법입니다.

python3 -m json.tool broken.json
jq . broken.json

오류 메시지 읽는 법

같은 실수라도 언어마다 메시지가 다릅니다. 자신의 메시지를 찾고, 원인을 확인하세요.

메시지(축약)나타나는 곳흔한 원인
Unexpected token '<', "<!DOCTYPE"... is not valid JSONJavaScriptJSON이 아니라 HTML 페이지를 받았습니다. 아래 참고
Unexpected end of JSON inputJavaScript빈 응답이거나 파일이 잘렸습니다
Expected double-quoted property nameJavaScript} 앞의 마지막 쉼표, 또는 따옴표가 없거나 작은따옴표인 키
Unexpected non-whitespace character after JSONJavaScript문서 두 개가 이어 붙었거나, 닫는 중괄호 뒤에 불필요한 내용이 있습니다
Bad control character in string literalJavaScript문자열 안에 탭이나 줄바꿈이 그대로 들어 있습니다
Expecting value: line 1 column 1 (char 0)Python빈 입력이거나 JSON이 아닙니다
Expecting property name enclosed in double quotesPython마지막 쉼표, 작은따옴표, 또는 따옴표 없는 키
Expecting ',' delimiterPython두 항목 또는 멤버 사이에 쉼표가 빠졌습니다
Extra dataPython파일에 문서가 둘 이상 있습니다(흔히 NDJSON)
Invalid control characterPython문자열 안에 탭이나 줄바꿈이 그대로 들어 있습니다
Unexpected UTF-8 BOMPython파일 맨 앞에 보이지 않는 바이트 순서 표시가 있습니다

원인을 하나씩 살펴보기

마지막 쉼표

{ "name": "Ada", "role": "admin", }

JavaScript 코드에서는 허용되지만 JSON에서는 금지입니다. 파서는 다음 키를 기대하다가 }를 만납니다. 마지막 쉼표를 지우세요. 손으로 편집한 설정 파일과 문자열 연결로 JSON을 만드는 코드에서 흔히 생깁니다.

작은따옴표

{ 'name': 'Ada' }

JSON 문자열은 항상 큰따옴표를 씁니다. 대개 Python dict를 json.dumps()가 아니라 print()로 출력해서 생깁니다. 진짜 해결책은 그것을 만든 코드에 있습니다. 문자열 포매팅이 아니라 JSON 라이브러리로 직렬화하세요.

따옴표 없는 키

{ name: "Ada" }

JavaScript로는 올바르지만 JSON으로는 잘못입니다. 모든 키를 따옴표로 감싸세요.

주석

{ "port": 8080 // default }

JSON에는 주석이 없습니다. 하지만 "고치기" 전에 주의하세요. 일부 파일은 주석이 있어도 되는 형식입니다. tsconfig.json, VS Code의 settings.json 등 많은 설정 파일은 JSONC(주석을 허용하는 JSON)나 JSON5이며, 이를 읽는 도구는 주석을 받아들입니다. 그런 파일이라면 문제는 파일이 아니라, 그것을 넘겨주는 엄격한 파서에 있습니다.

빠진 쉼표

{ "a": 1 "b": 2 }

파서는 실수보다 뒤에 있는 "b"에서 오류를 보고합니다. 오류가 멀쩡한 키를 가리키면, 그 앞 줄의 끝을 살펴보세요.

JSON에 없는 값

NaN, Infinity, undefined, 그리고 007처럼 0으로 시작하는 숫자는 모두 잘못입니다. 16진수 0xFF도 마찬가지입니다. 읽는 쪽이 기대하는 바에 따라 null, 문자열, 일반 10진수를 쓰세요.

문자열 안의 줄바꿈과 탭

문자열 안의 줄바꿈은 \n, 탭은 \t로 이스케이프해야 합니다. 따옴표 안의 실제 줄바꿈은 잘못입니다. 여러 줄 값을 JSON 파일에 손으로 붙여 넣을 때 자주 생깁니다.

백슬래시

"C:\new\folder" 같은 Windows 경로는 \n과 \f가 이스케이프 시퀀스라서 깨집니다. 백슬래시를 모두 두 번씩 쓰거나("C:\\new\\folder") 슬래시를 쓰세요.

둥근 따옴표

“name”은 문자열처럼 보이지만 아닙니다. 이것은 "가 아니라 타이포그래피용 따옴표입니다. 문서, 메신저, 슬라이드에서 JSON을 복사했거나, iPhone·iPad에서 입력할 때 스마트 문장 부호가 곧은 따옴표를 바꿔 버려서 생깁니다. iOS에서 JSON을 편집하기 전에 설정 → 일반 → 키보드에서 끄세요.

"위치 0" 오류: JSON이 아닙니다

오류가 맨 첫 글자에 있다면 문법이 아니라 내용이 잘못된 것입니다.

  • 위치 0의 < 는 HTML을 파싱했다는 뜻입니다. 서버가 오류 페이지, 로그인 페이지, 404를 돌려줬고, 코드가 그것을 JSON으로 읽으려 했습니다. 파싱하기 전에 원본 응답과 상태 코드를 로그로 남기세요.
  • 빈 입력 은 응답에 본문이 없다는 뜻입니다. 주로 204 No Content이거나, 서버가 응답하기 전에 실패한 요청입니다.
  • 맨 앞의 보이지 않는 문자 는 대개 Windows 편집기가 붙인 UTF-8 바이트 순서 표시입니다. Python에서는 encoding="utf-8-sig"로 파일을 열고, 다른 환경에서는 BOM 없는 UTF-8로 다시 저장하세요.

NDJSON은 깨진 JSON이 아닙니다

한 줄에 JSON 객체 하나씩 담은 파일(.jsonl, .ndjson, 로그 출력)은 두 번째 줄 시작 부분에서 "Extra data"나 "Unexpected non-whitespace"로 실패합니다. 각 줄은 그 자체로 올바릅니다. 줄 단위로 파싱하거나, 이 형식을 아는 도구를 쓰세요. jq -c . file.jsonl은 모든 줄을 읽습니다.

자동으로 복구하기

흔한 실수(마지막 쉼표, 작은따옴표, 따옴표 없는 키, 주석)는 타당한 해석이 하나뿐이어서 자동 복구가 안전합니다. 이를 해 주는 도구는 다음과 같습니다.

  • jsonrepair: JavaScript 라이브러리이자 명령줄 도구입니다.
  • 대부분의 코드 편집기: JSON5 또는 "fix JSON" 확장 프로그램을 통해 사용합니다.
  • 입력하는 동안 검증해 주는 JSON 편집기 앱.

잘린 파일에는 자동 복구가 안전하지 않습니다. 복구 도구는 열린 괄호를 닫아서, 데이터가 빠진 올바른 문서를 돌려줍니다. 그 대신 다시 가져오거나 다시 내보내세요.

iPhone과 iPad에서 Smart Json은 오류를 줄과 열과 함께 쉬운 말로 보여 줍니다. Go는 커서를 그 위치로 옮기고, Fix는 주석, 마지막 쉼표, 작은따옴표, 따옴표 없는 키를 한 번에 복구합니다.

편집기에 열린 한 줄로 압축된 JSON 문서와, 1행 2열에서 Expected a quoted key but found a stray character라고 표시하는 배너, 그리고 Go와 Fix 버튼
오류, 그 위치, 그리고 해결 방법
JSON Editor: Smart JsoniPhone 및 iPad

JSON 오류를 줄과 열과 함께 쉬운 말로 알려 주고, 그 위치로 이동하며, 주석, 마지막 쉼표, 작은따옴표, 따옴표 없는 키를 한 번의 탭으로 복구합니다.

기능

애초에 깨지지 않게 하기

잘못된 JSON 파일 대부분은 손으로 썼거나 문자열 연결로 조립한 것입니다. JSON은 직렬화기(json.dumps, JSON.stringify, JSONEncoder)로 생성하고, 손으로 편집한 파일은 커밋하기 전에 검증하세요. pre-commit 훅에서 jq . file.json > /dev/null을 실행하면 위의 문제를 다른 사람이 보기 전에 모두 잡아냅니다.

자주 묻는 질문

'Unexpected token < in JSON at position 0'은 무슨 뜻인가요?
JSON이 아니라 HTML을 파싱했다는 뜻입니다. 서버가 오류 페이지, 로그인 페이지, 404를 돌려줬고, 코드가 그것을 JSON으로 읽으려 한 것입니다. 파서를 호출하기 전에 원본 응답과 상태 코드를 로그로 남기세요.
JSON에서 마지막 쉼표를 써도 되나요?
안 됩니다. 객체나 배열의 마지막 항목 뒤에 쉼표가 있으면, JavaScript 코드에서는 허용되더라도 문서가 잘못된 JSON이 됩니다. 마지막 쉼표를 지우세요. JSON5와 JSONC 형식은 허용하지만 표준 JSON 파서는 허용하지 않습니다.
JSON에 주석을 쓸 수 있나요?
표준 JSON은 안 됩니다. JSONC(VS Code와 tsconfig.json에서 사용)나 JSON5처럼 JSON을 기반으로 한 일부 설정 형식은 주석을 허용하고, 그 파일을 읽는 도구도 받아들입니다. 엄격한 JSON 파서는 거부합니다.
내 JSON이 어디가 잘못됐는지 어떻게 찾나요?
위치를 알려 주는 검증기에 넣어 보세요. 명령줄에서는 python3 -m json.tool file.json 또는 jq . file.json, 아니면 오류에 밑줄을 그어 주는 JSON 편집기를 쓰면 됩니다. 실수는 보고된 위치나 그 바로 앞, 보통 앞 줄의 끝에 있습니다.
맞아 보이는데 왜 JSON이 잘못됐다고 나오나요?
맞아 보이지만 아닌 문자를 찾아보세요. 곧은 따옴표 대신 둥근 따옴표(문서에서 복사하거나 iPhone에서 입력할 때 흔합니다), 파일 맨 앞의 보이지 않는 바이트 순서 표시, 문자열 안에 그대로 들어간 탭 등이 있습니다.
잘못된 JSON을 자동으로 고칠 수 있나요?
흔한 실수는 가능합니다. 마지막 쉼표, 작은따옴표, 따옴표 없는 키, 주석은 각각 의미가 분명해서 jsonrepair 같은 도구로 안전하게 고칠 수 있습니다. 잘린 파일은 안전하게 고칠 수 없습니다. 복구 도구가 괄호를 닫아 버려서 빠진 데이터가 조용히 사라지기 때문입니다.

mygems — Smart Json을 만듭니다. 직접 작성한 파서가 이 오류들을 줄과 열로 알려 주고, 흔한 오류는 복구합니다.