JSON 비교 도구는 두 문서를 구조적으로 비교해 차이를 항목별로 나열합니다. 각 항목에는 JSON Pointer 경로, 종류(추가·삭제·변경), 관련된 값이 들어 있습니다. 배포 전후 API 응답을 비교하거나, 설정 마이그레이션이 무엇을 건드렸는지 확인하거나, 두 내보내기 결과가 정말 같은지 검증할 때 씁니다.
구조 비교이므로 공백과 키 순서는 영향을 주지 않습니다. {"a":1,"b":2}와 {"b":2,"a":1}은 같은 문서입니다. 배열은 위치로 비교하거나 순서 무시로 비교할 수 있고, 순서 무시에서는 같은 항목이 어디에 있든 서로 상쇄되어 남은 것만 보고됩니다. 결과는 변경 목록(행을 누르면 두 편집기에서 해당 줄로 이동), JSON 리포트, RFC 6902 연산의 JSON Patch로 볼 수 있습니다.
양쪽 입력은 각각 문법 검사를 거치며 줄·열과 오류 위치로 이동 버튼이 표시되므로 어느 문서가 잘못되었는지 바로 알 수 있습니다. 두 문서는 브라우저 안에서 해석되고 서버로 전송되지 않으며, 한쪽은 최대 20MiB이고 객체가 아닌 최상위 값도 됩니다.
사용 방법
원본과 변경본 붙여넣기
원본 JSON 칸에 이전 JSON을, 변경된 JSON 칸에 새 JSON을 넣거나 예제를 불러옵니다. 문법 오류는 해당 쪽 편집기에 줄·열과 오류 위치로 이동 버튼과 함께 표시됩니다.
배열 비교 방식 선택
배열을 위치로 비교로 두면
[1,2]와[2,1]은 두 위치 모두 다르고, 순서 무시로 두면 같은 항목이 어디에 있든 서로 상쇄됩니다.요약과 변경 목록 확인
추가, 삭제, 변경 개수가 표시됩니다. 변경 목록의 각 행에는 부호, JSON Pointer 경로, 이전·이후 값이 있으며 행을 누르면 두 편집기에서 해당 값으로 이동합니다.
리포트 또는 JSON Patch 탭 열기
리포트는 요약과 모든 변경을 담은 JSON 객체이고, JSON Patch는 원본을 변경본으로 바꾸는 RFC 6902 연산 목록입니다.
복사 또는 다운로드
보고 있는 탭을 복사하거나
diff-report.json,changes.patch.json으로 내려받습니다.
작동 원리
리포트 형식
리포트는 summary(added, removed, changed, total)와 changes 배열을 가진 JSON 객체입니다. 각 항목에는 path와 kind가 있고, before는 삭제와 변경 항목에, after는 추가와 변경 항목에 들어갑니다. 두 문서가 같으면 목록이 비고 키 순서를 무시하므로 문서가 같다는 메시지가 나옵니다.
두 값이 모두 객체이거나 모두 배열이면 안쪽으로 내려가며 비교합니다. 그 밖의 경우는 값 전체를 비교하므로, 스칼라 값이 바뀌었거나 타입이 달라진 경우(객체와 문자열, 숫자와 문자열 등)에는 이전 값과 새 값 전체를 담은 변경 항목 하나가 나옵니다.
{
"summary": { "added": 1, "removed": 0, "changed": 1, "total": 2 },
"changes": [
{ "path": "/age", "kind": "changed", "before": 30, "after": 31 },
{ "path": "/admin", "kind": "added", "after": true }
]
}JSON Pointer 경로
경로는 RFC 6901을 따릅니다. 각 단계는 슬래시로 시작하고 배열 위치는 0부터 시작하는 숫자이며 문서 전체는 빈 문자열((루트)로 표시)입니다. 키 이름 안의 ~는 ~0, /는 ~1로 쓰므로 키 a/b는 /a~1b로 나옵니다.
순서 무시 모드에서 변경·삭제 항목은 원본 배열의 위치를, 추가 항목은 변경본 배열의 위치를 경로에 씁니다. 변경 목록의 행을 눌렀을 때 이동하는 곳도 그 위치입니다.
위치로 비교와 순서 무시
위치로 비교하면 0번은 0번끼리, 1번은 1번끼리 비교하고, 더 긴 배열의 남는 위치는 추가 또는 삭제로 보고됩니다. 가볍고 예측하기 쉽지만 맨 앞에 원소 하나를 끼우면 뒤의 모든 위치가 변경으로 보입니다.
순서 무시에서는 반대편에 같은 항목이 있는 항목이 대응되는 개수만큼 서로 상쇄됩니다. 남은 항목은 위치 순서로 짝을 지으므로, 필드 하나가 바뀐 레코드는 통째로 삭제되고 추가된 것으로 나오지 않고 해당 필드 경로로 표시됩니다.
JSON Patch (RFC 6902)
JSON Patch 탭에는 add, remove, replace 연산이 나옵니다. 배열 삭제는 큰 인덱스부터 기록해 앞쪽 인덱스를 유지합니다. 패치를 적용한 결과와 변경 문서의 비교는 단위 테스트에서 확인하며 페이지가 실행 중에 검증하지는 않습니다.
비교에서 차이가 없으면 패치는 비어 있습니다([]). 순서 무시에서 [1,2]와 [2,1]이 같다고 판정되는 경우도 마찬가지입니다. 문서가 다르면 패치는 원본에서 변경본으로 가는 위치 기준 패치이며 어느 배열 모드에서든 유효합니다. 배열 항목의 순서까지 포함해 변경본을 정확히 재현합니다.
실제 예시
{"name":"Ada","age":30,"tags":["a","b"]}
---
{"age":31,"name":"Ada","tags":["a","b","c"],"admin":true}{
"summary": {
"added": 2,
"removed": 0,
"changed": 1,
"total": 3
},
"changes": [
{
"path": "/age",
"kind": "changed",
"before": 30,
"after": 31
},
{
"path": "/tags/2",
"kind": "added",
"after": "c"
},
{
"path": "/admin",
"kind": "added",
"after": true
}
]
}리포트 탭입니다. age가 바뀌었고 tags의 인덱스 2에 원소가 추가되었으며 admin이 새로 생겼습니다. 위치가 바뀐 name 키는 항목에 나오지 않습니다. 입력은 원본, --- 줄, 변경본 순서로 보여 줍니다.
[1,2,3]
---
[0,1,2,3]{
"summary": {
"added": 1,
"removed": 0,
"changed": 3,
"total": 4
},
"changes": [
{
"path": "/0",
"kind": "changed",
"before": 1,
"after": 0
},
{
"path": "/1",
"kind": "changed",
"before": 2,
"after": 1
},
{
"path": "/2",
"kind": "changed",
"before": 3,
"after": 2
},
{
"path": "/3",
"kind": "added",
"after": 3
}
]
}배열을 위치로 비교로 한 결과입니다. 밀린 위치는 모두 변경이고 마지막 위치는 추가입니다.
[1,2,3]
---
[0,1,2,3]{
"summary": {
"added": 1,
"removed": 0,
"changed": 0,
"total": 1
},
"changes": [
{
"path": "/0",
"kind": "added",
"after": 0
}
]
}배열을 순서 무시로 한 결과입니다. 1, 2, 3은 서로 상쇄되고 새로 생긴 0만 남아 변경본 배열의 위치로 보고됩니다.
[{"id":1,"n":"a"},{"id":2,"n":"b"}]
---
[{"id":2,"n":"B"},{"id":1,"n":"a"}]{
"summary": {
"added": 0,
"removed": 0,
"changed": 1,
"total": 1
},
"changes": [
{
"path": "/1/n",
"kind": "changed",
"before": "b",
"after": "B"
}
]
}순서 무시로 한 결과입니다. id 1 레코드는 상쇄되고 남은 것을 위치 순서로 짝지으므로 바뀐 필드 /1/n(b에서 B)만 원본 인덱스로 나옵니다.
{"a":1,"b":[1,2,3,4],"c":{"d":1}}
---
{"a":2,"b":[1,9],"c":{},"e":[1]}[
{
"op": "replace",
"path": "/a",
"value": 2
},
{
"op": "replace",
"path": "/b/1",
"value": 9
},
{
"op": "remove",
"path": "/b/3"
},
{
"op": "remove",
"path": "/b/2"
},
{
"op": "remove",
"path": "/c/d"
},
{
"op": "add",
"path": "/e",
"value": [
1
]
}
]JSON Patch 탭입니다. a와 b[1]은 교체되고, 배열의 3번과 2번 위치는 큰 인덱스부터 삭제되며, c/d는 삭제, e는 추가됩니다.
{"a/b":1,"x":{"y":1},"gone":null,"n":1,"s":"1"}
---
{"a/b":2,"x":"str","n":1.0,"s":1}{
"summary": {
"added": 0,
"removed": 1,
"changed": 3,
"total": 4
},
"changes": [
{
"path": "/a~1b",
"kind": "changed",
"before": 1,
"after": 2
},
{
"path": "/x",
"kind": "changed",
"before": {
"y": 1
},
"after": "str"
},
{
"path": "/gone",
"kind": "removed",
"before": null
},
{
"path": "/s",
"kind": "changed",
"before": "1",
"after": 1
}
]
}리포트 탭입니다. 키 a/b는 /a~1b로 쓰이고, 객체가 문자열로 바뀐 것은 두 값 전체를 담은 항목 하나이며, "1"과 1은 변경이고 1.0은 1과 같으므로 n은 나오지 않습니다.
자주 하는 실수
맨 앞 삽입은 전체를 밀어냅니다
위치로 비교하면 인덱스 0에 원소 하나를 넣을 때 뒤의 모든 인덱스가 변경으로 보이고 마지막에 추가가 하나 붙습니다. 목록의 순서가 중요하지 않다면 배열을 순서 무시로 바꾸세요.
순서 무시는 남은 항목을 위치로 짝지음
같은 항목은 상쇄되지만 서로 다른 레코드가 양쪽에 여러 개 남으면 나타나는 순서대로 짝이 지어집니다. 그래서 수정된 레코드가 엉뚱한 상대와 비교되어 예상보다 많은 필드 변경이 보일 수 있습니다.
숫자는 파싱된 값으로 비교됨
자릿수를 잃을 숫자는 정확한 원문을 보존해 비교하고 보고서와 패치에도 그대로 출력하므로 서로 다른 20자리 ID는 구분됩니다.
1.0과1은 숫자 값이 같습니다. 반복된 키는 마지막 값만 남으며 별도 메시지는 없습니다.변경 목록은 처음 300개만 표시
변경 목록 탭은 300행까지 보여 주고 나머지가 몇 개인지 알려 줍니다. 리포트 탭과 JSON Patch 탭에는 전부 들어 있습니다.
null과 키 없음은 다릅니다
{"a":null}과{}를 비교하면 키 자체가 사라졌으므로/a가before: null인 삭제로 보고됩니다.타입 변경은 항목 하나
객체가 문자열이나 null로 바뀌면 이전 키마다 삭제가 나오지 않고, 이전 값과 새 값 전체를 담은 변경 항목 하나가 나옵니다.
자주 묻는 질문
JSON 비교에서 키 순서도 보나요?
아니요. 객체는 키로 비교하므로 순서를 바꿔도 변경이 나오지 않습니다. 배열의 순서는 순서 무시를 고르지 않는 한 중요합니다.
배열 원소는 어떻게 비교하나요?
기본은 위치 기준입니다. 왼쪽 첫 원소와 오른쪽 첫 원소를 비교하는 식이며 한쪽에만 있는 원소는 추가 또는 삭제로 나옵니다. 순서 무시에서는 같은 항목을 먼저 상쇄하고 남은 것을 위치 순서로 짝짓습니다.
경로 /a~1b는 무슨 뜻인가요?
키 a/b를 가리킵니다. JSON Pointer에서는 키 안의 슬래시를 ~1, 물결표를 ~0으로 이스케이프해서 키와 구분자가 헷갈리지 않게 합니다.
비교 결과로 JSON Patch를 얻을 수 있나요?
네. JSON Patch 탭에 원본을 변경본으로 바꾸는 RFC 6902 add, remove, replace 연산이 나옵니다. 원본에 적용하면 변경된 JSON이 정확히 재현됩니다. 차이가 없으면 패치는 빈 목록입니다.
바뀐 줄을 문서에서 어떻게 찾나요?
변경 목록에서 행을 누르세요. 두 편집기가 해당 경로의 값으로 스크롤하며, 삭제·변경 항목은 원본에서, 추가·변경 항목은 변경본에서 위치를 찾습니다.
객체가 아닌 값도 비교할 수 있나요?
네. 배열, 문자열, 숫자, 불리언, null도 비교할 수 있습니다. 최상위 값이 다르면 빈 경로를 가진 항목 하나가 나옵니다.
데이터가 업로드되나요? 크기 제한은요?
업로드되지 않으며 두 문서 모두 브라우저 안에서 해석하고 비교합니다. 한쪽은 최대 20MiB이고 차이가 아주 많으면 브라우저에서 느려질 수 있습니다.
마지막 업데이트:
