JSON Stringify / Unstringify

JSON 객체를 코드에 삽입할 수 있는 한 줄짜리 따옴표 이스케이프 문자열로 변환하거나, 이스케이프된 JSON 문자열을 다시 읽기 쉬운 JSON으로 되돌립니다.

조회수 1,010회

작동 원리

Stringify는 실제 JSON을 받아 이스케이프 처리된 한 줄짜리 문자열 리터럴로 변환합니다 — 이는 JSON을 다른 JSON 필드, 설정 값, 또는 소스 코드의 문자열 상수 안에 삽입할 때 필요한 형태입니다. 내부적으로 이는 정확히 JavaScript의 JSON.stringify()가 하는 일과 같습니다: 값을 순회하며 문자열에 따옴표를 씌우고, 제어 문자와 내부 따옴표를 이스케이프 처리한 뒤, 객체와 배열을 텍스트로 직렬화합니다. Unstringify는 그 반대입니다: 이스케이프된 JSON 문자열(\"\n 포함)을 붙여넣으면 깔끔하고 읽기 쉬운, 들여쓰기된 JSON을 돌려받습니다.

구체적인 예: 객체 {"name":"Ada","tags":["a","b"]}는 리터럴 "{\"name\":\"Ada\",\"tags\":[\"a\",\"b\"]}"로 변환됩니다 — 내부의 큰따옴표마다 앞에 백슬래시가 붙어, 전체가 하나의 바깥쪽 따옴표 쌍 안에 들어갈 수 있게 됩니다. 이는 API가 JSON 페이로드를 다른 JSON 응답(웹훅 본문, 로그 한 줄, 텍스트 타입의 데이터베이스 컬럼 등) 안에 문자열로 감쌀 때, 또는 JSON 값을 주변 문법을 깨뜨리지 않고 YAML 파일, 환경 변수, 소스 코드의 문자열 상수 안에 넣어야 할 때 정확히 일어나는 일입니다. Unstringify는 그 반대 작업을 합니다: 이스케이프된 그 덩어리를 붙여넣으면 원래의 들여쓰기된 읽기 쉬운 형태로 돌려받습니다.

JSON.stringify()의 몇 가지 동작은 이 도구를 직접 쓰지 않더라도 알아둘 가치가 있습니다: undefined 값과 함수는 객체 속성에서 조용히 제거됩니다(값이 undefined인 키는 그냥 사라집니다). 하지만 배열 안의 같은 값은 제거되지 않고 null로 변환되는데, 배열은 길이와 인덱스 위치를 그대로 유지해야 하기 때문입니다. Date 객체는 객체 형태로 직렬화되지 않고, toJSON() 메서드를 통해 "2024-01-15T10:30:00.000Z" 같은 ISO 8601 문자열로 변환됩니다. 그리고 순환 참조를 포함한 값 — 직접적으로든 속성 체인을 통해서든 자기 자신을 다시 가리키는 객체 — 는 아예 문자열로 변환할 수 없습니다: 실제 JSON.stringify()TypeError: Converting circular structure to JSON을 던지는데, 무한히 중첩된 구조를 표현할 수 있는 유한한 문자열이 존재하지 않기 때문입니다.

알아두어야 할 점

Stringify는 한 가지 특정한 의미에서 손실이 있는 작업입니다: 조용히 제거되는 것들(함수, undefined 속성, Symbol 키)은 이후 unstringify를 해도 복원할 수 없습니다 — 왕복 변환은 애초에 유효한 JSON이 표현할 수 있는 것, 즉 문자열, 숫자, 불리언, null, 일반 객체와 배열만 보존합니다. 실제 코드에서 JSON.stringify()는 값 자체 외에 두 개의 추가 인자를 받을 수 있습니다: replacer(어떤 속성을 포함할지, 또는 직렬화 전에 값을 어떻게 변환할지를 정확히 제어하는 함수 또는 키 이름 배열)와 space 매개변수(압축된 한 줄짜리 출력을 들여쓰기된 사람이 읽기 쉬운 JSON으로 바꾸는 숫자 또는 문자열 — 이것이 바로 압축된 API 응답과 디버거가 보여주는 보기 좋게 정리된 버전의 차이입니다).

이중 인코딩된 JSON은 흔한 혼란의 원인입니다: 어떤 값이 JSON 문자열처럼 보이는데 맨 첫 글자가 따옴표이고 내부에 백슬래시로 이스케이프된 따옴표가 가득하다면, 그것은 이미 두 번 stringify된 것일 가능성이 높습니다 — 한 번은 애플리케이션에서, 또 한 번은 페이로드가 이미 JSON 문자열이라는 것을 몰랐던 다른 계층에서. unstringify를 한 번 실행하면 바깥쪽 계층이 풀립니다; 결과가 여전히 이스케이프된 것처럼 보인다면 다시 한 번 실행하십시오.

자주 묻는 질문

코드에서 쓰는 JSON.stringify와 무엇이 다른가요?

동일한 작업을 대화형 도구로 제공하는 것뿐입니다. 실제 JSON을 붙여넣으면, 콘솔이 없을 때 JSON.stringify(obj)를 실행해야 얻을 수 있는 이스케이프된 문자열 형태를 바로 얻을 수 있습니다.

JSON을 unstringify해야 하는 경우는 언제인가요?

API나 로그는 때때로 JSON 문자열을 다른 JSON 필드 안에 중첩시킵니다(이중 인코딩된 JSON) — unstringify는 그 내부의 이스케이프된 문자열을 읽기 쉽고 파싱 가능한 JSON으로 되돌려줍니다.

스트링화한 후 속성이 사라진 이유는 무엇인가요?

JSON.stringify()는 값이 undefined이거나 함수인 객체 속성을 조용히 생략합니다 — 둘 다 JSON으로 표현할 방법이 없으므로, null로 직렬화되는 대신 키 자체가 완전히 제거됩니다. 배열 안의 같은 undefined 값은 사라지지 않고 null이 되는데, 배열은 길이와 인덱스 순서를 유지해야 하기 때문입니다.

"circular structure" 오류는 왜 발생하나요?

객체가 직접적으로든 다른 객체의 체인을 통해서든 자기 자신을 참조하면, JSON.stringify()는 유한한 문자열을 만들 수 없어 TypeError를 던집니다. 이는 부모를 다시 가리키는 역참조를 가진 객체(트리를 가리키는 자식 노드, DOM 요소, "self" 필드를 가진 클래스 인스턴스 등)를 직렬화할 때 흔히 발생합니다 — 해결책은 직렬화 전에 순환 속성을 제거하거나 대체하는 것이며, 보통 replacer 함수를 사용합니다.

제 데이터가 어딘가에 업로드되나요?

아니요 — 두 방향 모두 브라우저 안에서 로컬로 실행됩니다.

댓글

아직 댓글이 없습니다 — 첫 댓글을 남겨보세요!

비슷한 도구