숏컷 코드
[
"text",
42,
true,
null,
{ "x": 1 },
[1, 2, 3]
]문법
여섯 가지 타입만 허용한다 — 그 외 값은 JSON으로 직렬화할 수 없다
JSON 값은 string, number, boolean, null, object, array로 정확히 여섯 종류입니다. JavaScript의 undefined, 함수, Symbol, BigInt, Date 객체는 JSON 값이 아닙니다. JSON.stringify()로 직렬화할 때 undefined와 함수는 object 멤버에서 제외되고 array 안에서는 null로 대체됩니다. 이 동작은 조용히 데이터를 잃어버리기 때문에, 직렬화 전후 값 비교가 필요한 경우라면 타입별로 별도 변환 규칙을 설계해야 합니다.
true, false, null은 정확히 소문자여야 한다 — 대소문자 혼용은 파싱 오류를 낸다
JSON spec은 boolean literal을 true, false로, null literal을 null로 정확히 지정합니다. True, False, NULL, Null 같은 표기는 모두 유효하지 않습니다. 이 규칙이 엄격한 이유는 JSON grammar가 이 세 단어를 token으로 예약해 두었기 때문입니다. Python의 True/False나 SQL의 NULL처럼 다른 언어 관습과 혼동해 대문자로 쓰면 파싱 단계에서 즉시 오류가 발생합니다.
{ "active": true, "deleted": false, "nickname": null }null은 "값 없음"을 표현하는 명시적 값이다 — 키 부재와 혼용하면 파싱 코드가 두 경우를 모두 처리해야 한다
null은 JSON 값의 한 종류이지 "키가 없음"의 동의어가 아닙니다. {"nickname": null}은 nickname 키가 존재하되 값이 비어 있음을 명시하는 것이고, 키 자체가 없는 {}는 그 필드가 아예 전달되지 않은 상태를 뜻합니다. API 응답과 PATCH 요청에서 이 두 상태를 구별하지 않으면 소비자가 "의도적 초기화"와 "필드 미포함"을 같은 방식으로 처리해야 하고, 버그가 숨기 좋은 구조가 됩니다.
실무에서는 "필드가 없으면 유지"인지, "null이면 지우기"인지를 문서로 고정해야 합니다. 이 규칙이 없으면 같은 payload를 두고 서버와 클라이언트가 서로 다른 해석을 하게 됩니다.
최상위 값은 object나 array가 아니어도 된다 — 그러나 실제 상호운용성은 그렇지 않다
RFC 8259 기준으로 JSON text는 단일 값이면 충분합니다. "hello", 42, null 같은 primitive도 유효한 JSON text입니다. 그러나 일부 오래된 파서와 라이브러리는 최상위가 object나 array일 때만 올바르게 동작합니다. API 응답과 설정 파일에서 최상위를 object로 두는 관행은 이 호환성 문제를 피하기 위한 실용적 선택이며, 나중에 메타데이터를 추가할 때 구조 변경 없이 필드만 추가할 수 있다는 확장성도 이유 중 하나입니다.
{
"name": "Kim",
"active": true,
"nickname": null
}선택 기준
| 상황 | 적합한 선택 |
|---|---|
| 값이 존재하지 않음을 명시해야 할 때 | null (키와 값 모두 포함) |
| 필드 자체를 전달하지 않을 때 | 키를 아예 생략 |
| boolean 값 표현 | true / false (소문자 고정) |
| 최상위 구조 선택 | object 권장 (확장성, 호환성) |
| PATCH처럼 "유지"와 "초기화"를 구분해야 할 때 | missing과 null 의미를 계약에 명시 |
주의할 점
null은 값의 한 종류이지 "키가 없음"과 같지 않습니다. true, false, null은 반드시
소문자로 써야 하며, Python의 True/False나 SQL의 NULL처럼 대문자로 쓰면 파싱 오류가
납니다. undefined나 함수를 담은 값을 JSON.stringify()로 직렬화하면 데이터가 조용히
사라지거나 null로 바뀌므로, 직렬화 전 타입을 반드시 확인해야 합니다.
{
"active": True,
"nickname": undefined
}이 형태는 JavaScript 코드 문맥에서는 익숙해 보여도 JSON으로는 유효하지 않습니다. 특히 True, undefined는 다른 언어 습관이 섞여 들어올 때 자주 생기는 오류다.
참고 링크
2 sources