JSON 차이 비교
두 JSON 객체를 비교하고 차이를 시각화. RFC 6902 JSON Patch 작업과 색상 코딩 트리 차이 출력. 완전 클라이언트사이드.
- 브라우저에서 처리
- 데이터가 브라우저 밖으로 나가지 않습니다
- 무료 · 회원가입 불필요
WeChat으로 스캔하여 공유
예시·자세한 설명·자주 묻는 질문 실제 출력이 있는 예시, 다른 도구와의 차이, 자주 묻는 질문.
사용 사례
- 버전 간 API 응답 변경 사항 검토.
- PATCH HTTP 엔드포인트용 패치 작업 생성.
- 설정 파일 변경 감사.
- 애플리케이션의 예상치 못한 데이터 변이 디버그.
관련 도구: JSON Formatter (JSON 정렬) — 비교 전 JSON을 정리하고 검증합니다.
예시
이전:
{"name":"Alice","status":"pending","legacy_id":12345,"tags":["a","b","c"],"profile":{"age":30,"city":"Paris"}}
이후(키 순서 변경, status 변경, legacy_id 삭제, role 추가, 첫 번째 태그 삭제):
{"status":"active","name":"Alice","role":"admin","tags":["b","c"],"profile":{"age":31,"city":"Paris"}}
시각적 diff:
~status: "pending" → "active"
−legacy_id: 12345
~tags.0: "a" → "b"
~tags.1: "b" → "c"
−tags.2: "c"
~profile.age: 30 → 31
+role: "admin"
JSON Patch:
[
{ "op": "replace", "path": "/status", "value": "active" },
{ "op": "remove", "path": "/legacy_id" },
{ "op": "replace", "path": "/tags/0", "value": "b" },
{ "op": "replace", "path": "/tags/1", "value": "c" },
{ "op": "remove", "path": "/tags/2" },
{ "op": "replace", "path": "/profile/age", "value": 31 },
{ "op": "add", "path": "/role", "value": "admin" }
]
키 순서는 결과에 영향을 주지 않습니다. name은 위치가 바뀌었지만 보고되지 않습니다. 이 patch를 Python jsonpatch 1.33으로 적용하면 이후 문서가 됩니다:
import jsonpatch # pip install jsonpatch
before = {"name": "Alice", "status": "pending", "legacy_id": 12345,
"tags": ["a", "b", "c"], "profile": {"age": 30, "city": "Paris"}}
patch = jsonpatch.JsonPatch([...]) # paste the patch from the tool
after = patch.apply(before)
배열 비교 방식
배열은 내용이 아니라 인덱스로 비교합니다. ["a","b","c"]에서 첫 번째 태그를 빼면 remove /tags/0 하나가 아니라 교체 두 개와 삭제 하나로 표시됩니다. patch는 올바르지만 필요 이상으로 깁니다.
같은 배열에서 여러 요소를 지우면 삭제는 큰 인덱스부터 씁니다. 예를 들어 주문 항목 3개가 1개로 줄고 수량도 바뀐 경우:
[
{ "op": "replace", "path": "/items/0/qty", "value": 3 },
{ "op": "remove", "path": "/items/2" },
{ "op": "remove", "path": "/items/1" }
]
remove /items/2 뒤에도 배열에 2개가 남아 있으므로 /items/1은 여전히 존재합니다. 작은 인덱스부터 쓰면 두 번째 삭제가 배열 끝을 넘어가고, 연산 하나라도 실패하면 패치 전체가 실패합니다(RFC 6902 5절). 짧은 쪽 배열을 넘는 요소는 remove(큰 인덱스부터) 또는 add(작은 인덱스부터)가 됩니다.
경로와 JSON Pointer 이스케이프
patch 경로는 JSON Pointer(RFC 6901)입니다. ~는 ~0, /는 ~1로 씁니다. {"a/b":1,"m~n":2,"list":[1,2,3]} → {"a/b":2,"list":[1,2,3,4],"x":null}의 결과:
[
{ "op": "replace", "path": "/a~1b", "value": 2 },
{ "op": "remove", "path": "/m~0n" },
{ "op": "add", "path": "/list/3", "value": 4 },
{ "op": "add", "path": "/x", "value": null }
]
루트 타입이 다르면(객체와 배열 등) 패치는 문서 전체를 교체하고 경로는 빈 문자열 ""입니다(RFC 6901에서 /는 이름이 빈 문자열인 멤버를 가리킴):
[
{ "op": "replace", "path": "", "value": [1] }
]
시각적 diff는 키를 점으로 이어 보여 줍니다(profile.age, list.3). 읽기용 표기이므로 코드에서는 JSON Patch의 경로를 쓰세요.
제한 사항
- move, copy 연산은 만들지 않습니다. 이름이 바뀐 키는
remove와add로 표시됩니다. - 객체 배열을
id필드로 짝짓지 않습니다. - 양쪽 모두 유효한 JSON이어야 합니다. 상태 표시에 어느 쪽 파싱이 실패했는지 나옵니다(예:
이전 JSON 파싱 오류: Expected double-quoted property name in JSON at position 7). - 숫자는 JavaScript로 파싱한 뒤 비교하므로
1.0과1은 같고, 2^53을 넘는 정수는 정밀도를 잃습니다. - 도구의 테스트는 생성한 패치를 엄격한 RFC 6902 구현(설치되어 있으면 Python
jsonpatch도)으로 “이전”에 적용해 결과가 “이후”와 같은지 확인하며, 무작위 문서 3,000쌍도 검사합니다.
FAQ
RFC 6902 JSON Patch란 무엇인가요?
RFC 6902는 JSON 문서에 적용할 일련의 작업을 표현하는 JSON 문서 형식을 정의합니다. 각 작업은 'op'(add/remove/replace/move/copy/test), 'path'(RFC 6901 JSON Pointer), 그리고 선택적 'value'를 가진 객체입니다.
JSON 데이터가 서버로 전송되나요?
아닙니다. 비교는 브라우저의 JavaScript에서 실행됩니다. 어떤 데이터도 외부로 나가지 않습니다.
큰 JSON 파일도 비교할 수 있나요?
네, 하지만 수천 개의 키나 깊게 중첩된 배열을 가진 매우 큰 객체는 처리에 시간이 걸릴 수 있습니다. 모든 계산은 브라우저 내에서 완결됩니다.
비주얼 차이 비교는 어떻게 작동하나요?
도구는 깊은 재귀 비교를 수행합니다. 'After'에만 있는 키는 추가(+)로 표시됩니다. 'Before'에만 있는 키는 삭제(−)로 표시됩니다. 값이 변경된 키는 변경(~)으로 이전 값과 새 값을 함께 표시합니다.
텍스트 차이 비교 도구와 무엇이 다른가요?
텍스트 차이 비교 도구는 일반 텍스트를 줄 단위로 비교합니다. 이 JSON 차이 도구는 JSON 구조를 이해하고 텍스트가 아닌 의미론적으로 값을 비교하며, 기계 판독 가능한 JSON Patch 작업을 출력합니다.