본문으로 건너뛰기
김신건의 로그

[Javascript] JSON

· 수정 · 📖 약 1분 · 327자/단어 #javascript #json #serialization
JS JSON, JSON.stringify, JSON.parse

정의

JSON (JavaScript Object Notation) 은 데이터 교환 형식. JS 의 객체 리터럴과 비슷하지만 엄격한 문법.

  • JSON.stringify(value) : JS 값 → JSON 문자열
  • JSON.parse(text) : JSON 문자열 → JS 값

stringify

JSON.stringify({ a: 1, b: [2, 3] })
// '{"a":1,"b":[2,3]}'

JSON.stringify({ a: 1 }, null, 2)
// pretty-print, 2-space indent
// {
//   "a": 1
// }

parse

JSON.parse('{"a":1}')        // { a: 1 }
JSON.parse('[1, 2, 3]')      // [1, 2, 3]
JSON.parse('null')            // null
JSON.parse('true')            // true
JSON.parse('"hello"')         // 'hello'

replacer (stringify)

JSON.stringify({ a: 1, password: 'secret' }, (key, value) => {
    return key === 'password' ? undefined : value;
});
// '{"a":1}'

// 또는 array (allowlist)
JSON.stringify(obj, ['a', 'b']);    // a, b 만 포함

reviver (parse)

JSON.parse(text, (key, value) => {
    if (key === 'date') return new Date(value);
    return value;
});

date / BigInt 등 표준 외 타입 복원에 유용.

누락되는 값들

stringify 가 무시하거나 변환하는 값:

입력결과
undefined (값)키 제외
undefined (배열 원소)null
Symbol (값)키 제외
function키 제외
NaN, Infinitynull
DatetoISOString() 호출 → string
BigInt❌ TypeError
순환 참조❌ TypeError
JSON.stringify({
    a: undefined,
    b: Symbol(),
    c: () => {},
    d: NaN,
    e: new Date(),
    f: 1n,    // ❌
});
// '{"d":null,"e":"2024-..."}'   (a, b, c 제외)

toJSON 메서드

객체에 toJSON 메서드가 있으면 stringify 가 호출.

class Money {
    constructor(amount) { this.amount = amount; }
    toJSON() {
        return `$${this.amount.toFixed(2)}`;
    }
}

JSON.stringify(new Money(99.9));    // '"$99.90"'

Date 가 ISO string 되는 것도 이 메커니즘.

깊은 복사 (제한적)

const copy = JSON.parse(JSON.stringify(obj));

장점: 단순. 단점:

  • Date → string 으로 변환됨
  • function, undefined, Symbol 누락
  • BigInt, 순환 참조 에러

깊은 복사는 structuredClone(obj) 권장 (ES2022+).

자주 쓰는 패턴

API 통신

const response = await fetch('/api', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
});
const json = await response.json();   // 내부적으로 JSON.parse

localStorage

localStorage.setItem('user', JSON.stringify(user));
const user = JSON.parse(localStorage.getItem('user'));

디버깅 출력

console.log(JSON.stringify(complexObj, null, 2));

보안 (민감 정보 제거)

function sanitize(obj) {
    return JSON.parse(JSON.stringify(obj, (k, v) =>
        ['password', 'token', 'apiKey'].includes(k) ? undefined : v
    ));
}

함정

1. 한국어 escape

JSON.stringify({ name: '한글' })
// '{"name":"한글"}'  (UTF-8 그대로)

// 옛 환경 호환을 위해 ASCII 만 원한다면 직접 escape

2. 정수 정밀도

JSON.parse('9007199254740993')      // 9007199254740992 (정밀도 손실)

큰 정수는 JSON 문자열 → BigInt 수동 변환.

3. 순환 참조

const a = {};
a.self = a;
JSON.stringify(a)    // ❌ TypeError

해법: replacer 로 순환 감지 또는 외부 라이브러리.

4. 키 순서

JSON.parse(JSON.stringify(obj))
// 객체 키 순서가 보존되긴 하지만 표준은 보장 안 함

비교/해시에 키 순서를 의존하지 말 것.

JSON5 / JSONC

{
    // 주석 가능
    "a": 1,
    "b": 2,    // trailing comma
}

JSON 의 확장 (주석, 후행 쉼표). 표준이 아니라 라이브러리 필요. tsconfig.json 이 JSONC 사용.

참고

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기