JSON 숫자 타입 하나, 그리고 그건 float
JSON 숫자는 IEEE 754 배정밀도 float 으로 떨어져. spec 에 정수 타입이 따로 없어서 5 와 5.0 은 같은 값이야. 파서 대부분이 내부적으로는 정수와 float 을 구분해 두지만, 그건 spec 이 시킨 게 아니라 구현이 알아서 해주는 거고.
문법 규칙
- 맨 앞 0 금지 —
007은 안 되고7로 써. - 양수에
+금지 —+5는 안 되고5로 써. - 소수점 양쪽에 숫자 필요 —
.5와5.는 안 되고0.5,5.0으로 써. - 지수 표기는 돼 —
1e6,1.5e-3,2E10다 유효해. - NaN 과 Infinity 는 안 돼 —
null로 바꿔 보내거나, 관행대로 표시를 단 문자열로 보내.
253 정밀도 절벽
JS 숫자는, 그리고 JSON 파서 대부분은 Number.MAX_SAFE_INTEGER (= 253 - 1 = 9,007,199,254,740,991) 를 넘어가면 정수 정밀도를 잃어. 64 비트 Twitter ID, Stripe object ID, 데이터베이스 BIGINT 가 여길 지나가면 아무 경고 없이 반올림돼. 큰 정수는 문자열 로 보내.
Twitter ID 버그: Twitter API 는 64 비트 tweet ID 를 돌려줬어. 그런데 10 년 동안 순진하게 짠 JS 클라이언트들이 253 넘는 ID 를 조용히 망가뜨리고 있었지. 결국 Twitter 문서가
id 말고 id_str 을 읽으라고 안내하기에 이르렀어. 큰 정수를 JSON 숫자로 보내는 API 는 지뢰밭이야. 문서에 따로 못 박아두지 않았으면 문자열이라고 치고 들어가.