JSON.stringify의 두 번째 인자

Keonwoo Kim·2025년 7월 26일

JSON.stringify의 첫 번째 인자는 (당연히) 사용해 봤을 것이고, 세 번째 인자(indent level)도 자주 사용한다. 그러면 두 번째 인자는 무엇인가? 우연히 두 번째 인자를 사용하는 코드를 봐서 찾아보게 되었다.

MDN 문서

tl;dr

두 번째 인자(replacer)에는 배열(unknown[])이나 함수((key: string, value: unknown) => any)가 들어갈 수 있다. (다른 게 들어가면 안 준 거나 마찬가지로 동작한다.)

  • 배열이라면, 배열 안에 있는 key: string | number만 stringified JSON에 포함된다.
JSON.stringify({ hello: "world", hi: "there", [Symbol. }, ["hi"])
> '{"hi":"there"}'
  • 함수라면, stringify 중에 만나는 key와 그 value를 파라미터로 하여 함수를 호출한다.
    • 리턴 값이 number | string | boolean | null이면 그 값을 그대로 사용한다.
    • 리턴 값이 Function | Symbol | undefined이면 그 값은 결과에 포함되지 않는다.
    • 리턴 값이 object이면 재귀적으로 다시 replacer 함수를 호출한다.

주의점

주의할 점은, 최상단 오브젝트 자체에 대해서도 replacer가 호출된다는 것이다. 부모 오브젝트에 대해서 호출하고 나서 각 key와 상응하는 value로 replacer를 호출한다. 예를 들어, JSON.stringify(<아무거나>, () => 42)는 언제나 42가 된다.

JSON.stringify(
  // value
  { createdAt: new Date() },
  // replacer
  (key, value) =>
    value instanceof Date ?
      value.toLocaleString("ko-KR") :
      value,
  // space
  2,
)

> `{
  "createdAt": "2025-07-26T11:23:10.961Z"
}`

...?
다시 읽어보니 replacervalue는 stringified가 되어서 온다고 한다. (대체 왜???)
그래서 이 문제를 타파하기 위해서는 value 대신 this[key]를 사용해야 한다. Arrow function에서는 this가 상위 환경의 값이 되어버리므로 function으로 수정하자.

JSON.stringify(
  // value
  { createdAt: new Date() },
  // replacer
  function (key, value) {
    return (
      this[key] instanceof Date ?
        this[key].toLocaleString("ko-KR") :
        value
    );
  },
  // space
  2,
)

> `{
  "createdAt": "2025. 7. 26. 오후 8:39:20"
}`

Date나 Map, Set 등이 포함되어 있을 때에 superjson 없이 간단하게 사용하기 좋을 것 같다.

되살리기 (JSON.parse)

JSON.parse에도 같은 역할을 하는 reviver라는 인자가 있다고 한다!

0개의 댓글