JSON 검증기
모든 오류의 정확한 행, 열, 원인, 해결 방법을 보여 줍니다.
붙여 넣은 것은 여러분의 브라우저를 떠나지 않습니다. connect-src 허용 목록 덕분에 이는 약속이 아니라 브라우저가 강제하는 보장입니다. 직접 확인하기
검증이 답하는 질문은 하나입니다. 이것이 올바른 JSON 문서인가? 쓸모 있는 부분은 답이 "아니오"일 때 벌어지는 일입니다. 대부분의 검증기는 예기치 않은 토큰이 있다고만 말하고 찾는 일은 여러분에게 넘깁니다. 이 도구는 어떤 문자가, 몇 번째 행과 열에서, 대신 무엇을 기대했는지, 그리고 어떻게 고치면 되는지까지 알려 줍니다.
첫 번째 문제에서 멈추지도 않습니다. 네 군데가 잘못된 문서는 네 건으로 보고되므로, 네 번이 아니라 한 번에 고칠 수 있습니다.
무엇을 검사하는가
RFC 8259의 문법 전체입니다. 사람들이 의외라고 여기는 부분까지 포함해서요.
- 공백
- 토큰 사이에 올 수 있는 문자는 공백, 탭, 캐리지 리턴, 라인 피드 네 가지뿐입니다. 줄바꿈 없는 공백, 폭이 0인 공백, 전각 공백은 모두 문법 오류이고, 이 검증기는 예기치 않은 토큰이라고 하는 대신 그 문자의 이름을 알려 줍니다. 웹 페이지, PDF, 채팅 클라이언트에서 JSON을 복사할 때 끊임없이 딸려 옵니다.
- 숫자
- 앞자리 0, 앞의 플러스 기호, 16진수, 끝에 남은 소수점, NaN, Infinity 모두 안 됩니다. 원인도 해결책도 다르기 때문에 위반마다 따로 메시지를 냅니다.
- 문자열
- 허용되는 이스케이프 시퀀스는 아홉 가지뿐입니다. U+0020 미만의 제어 문자는 반드시 이스케이프해야 합니다. 짝 없는 서로게이트는 경고로 표시합니다. 파싱은 되지만 UTF-8로 다시 인코딩하면 살아남지 못하기 때문입니다.
- 최상위 값은 하나
- 한 문서는 정확히 하나를 담습니다. 한 줄에 하나씩 값이 여러 개 있는 것은 NDJSON이고, 이 검증기는 그 형태를 알아보고 일반적인 "뒤에 내용이 더 있음" 오류 대신 그렇게 알려 줍니다.
오류가 아닌 경고
파싱은 되는데도 오후를 망치는 것들이 있습니다. 출력을 막지 않도록 따로 보고합니다.
- 중복 키
- RFC 8259는 키가 유일해야 한다(SHOULD)고만 말하고 중복일 때의 동작은 정의하지 않습니다. JavaScript와 Python은 마지막 것을, 일부 Go와 Java 파서는 문서 자체를 거부하고, 일부는 첫 번째를 택합니다. 여기서는 두 위치를 모두 알려 줍니다.
- 안전 범위를 벗어난 정수
- 2^53-1을 넘으면 JavaScript 숫자는 값을 정확히 담을 수 없습니다. 경고에는 JSON.parse가 대신 돌려줄 값이 함께 표시됩니다.
- 바이트 순서 표식
- 앞에 붙은 U+FEFF는 여기서는 받아들이고 보고합니다. 브라우저와 Node의 JSON.parse는 이를 그대로 거부하기 때문입니다.
- 아주 깊은 중첩
- 이 파서는 반복형이라 깊이 제한이 없지만, 받아 쓰는 쪽은 대개 제한이 있습니다. 이 머신에서 측정한 결과 V8은 약 4,800단계보다 깊은 구조의 직렬화를 거부합니다. 읽을 수 있는 문서가 다시 써낼 수 없는 문서일 수 있다는 뜻입니다.
문법뿐 아니라 구조도 검증하기
문법 검증은 문서가 형식에 맞는다는 것만 알려 줄 뿐, 기대한 내용이 들어 있는지는 알려 주지 않습니다. 그건 JSON Schema의 몫으로, 필수 속성과 타입과 제약을 기술합니다. 저희 스키마 생성기는 샘플 페이로드에서 출발점이 될 스키마를 만들어 줍니다.
How to do this in code
코드로 유효성을 확인하고, 거기서 쓸 만한 오류 정보를 뽑아내는 방법입니다.
js JavaScript
표준 라이브러리에는 예외를 던지지 않는 검증기가 없어서, try/catch가 곧 API입니다.
function validate(text) {
try {
JSON.parse(text);
return { ok: true };
} catch (e) {
// Modern V8 includes a (line L column C) suffix in the message.
return { ok: false, message: e.message };
}
} py Python
JSONDecodeError는 msg, lineno, colno, pos, doc을 담고 있어 대부분의 런타임보다 구조화된 정보를 줍니다.
import json
try:
json.loads(text)
except json.JSONDecodeError as e:
print(f"{e.msg} at line {e.lineno} column {e.colno} (char {e.pos})") sh Shell
jq empty는 입력을 파싱하고 아무것도 출력하지 않아서, CI 스크립트 안의 유효성 검사로 깔끔하게 쓸 수 있습니다.
# jq exits non-zero and prints the position on failure
jq empty input.json
# Python, no extra install
python -m json.tool input.json > /dev/null go Go
Go는 행이 아니라 바이트 오프셋을 알려 주므로 줄바꿈은 직접 세어야 합니다.
if !json.Valid(data) {
// Valid() gives no position. To get one, decode and
// inspect the SyntaxError:
var v any
if err := json.Unmarshal(data, &v); err != nil {
var se *json.SyntaxError
if errors.As(err, &se) {
line := 1 + bytes.Count(data[:se.Offset], []byte("\n"))
return fmt.Errorf("%v at line %d", se, line)
}
}
} 자주 묻는 질문
- 다른 검증기는 하나만 보고하는데 왜 여러 개를 보고하나요?
- 파서가 멈추지 않고 복구하기 때문입니다. 문제를 보고한 뒤 다시 동기화해서 계속 진행하므로, 끝쉼표와 작은따옴표 문자열과 따옴표 없는 키가 함께 있는 문서라면 세 가지를 한 번에 모두 보고합니다.
- 문자열이나 숫자 하나만 있어도 유효한 JSON인가요?
- 네, 2014년 RFC 7159부터 그렇습니다. 원래의 RFC 4627은 최상위 값이 객체나 배열이어야 한다고 요구했지만, 현재 명세인 RFC 8259는 어떤 값이든 허용합니다. 따라서 "hello", 42, null은 모두 완결된 유효한 JSON 문서입니다.
- 끝쉼표가 허용되는 경우도 있나요?
- JSON에서는 없습니다. JavaScript, JSON5, 그리고 VS Code가 자체 설정 파일에 쓰는 JSONC에서는 허용됩니다. 받는 쪽이 JSONC를 받아들인다면 남겨도 되고, 아니라면 복구 도구가 제거해 줍니다.
- 주석은요?
- JSON에는 설계상 없습니다. 더글러스 크락포드가 일부러 뺐는데, 사람들이 주석에 파싱 지시문을 넣어 쓰고 있었기 때문입니다. JSONC나 JSON5를 쓰거나, 설명을 "_comment" 같은 키로 옮기세요.