JSON 비교
두 JSON 문서를 비교해 무엇이 추가·삭제·변경됐는지 확인합니다. 키 순서와 들여쓰기, 압축 여부는 무시되며 데이터는 브라우저를 떠나지 않습니다.
두 창에 JSON을 붙여 넣으면 비교합니다
적힌 모양이 아니라 데이터를 견주기
줄 단위 비교는 적힌 모양에 대한 물음에 답합니다. 이 파일의 어느 줄이 저 파일의 줄이 아닌가 하는 물음입니다. 산문과 소스 코드에는 그것이 맞는 물음이지만 JSON에는 틀린 물음입니다. JSON 문서에는 유일하게 옳은 적는 법이 없기 때문입니다. 객체의 멤버를 다시 늘어놓거나 들여쓰기를 바꾸거나 한쪽을 압축하면 모든 줄이 바뀌는데 데이터는 조금도 움직이지 않습니다. 이 도구는 두 문서가 구문 분석된 결과를 견주므로, 알려 주는 것은 실제로 바뀐 것입니다. 아래는 같은 문서를 두 번 적은 것입니다. 첫 줄은 압축한 것이고, 그다음은 서식을 넣고 멤버를 다른 순서로 놓은 것입니다.
{"name":"checkout","port":8080,"tags":["a","b"]}
{
"port": 8080,
"tags": ["a", "b"],
"name": "checkout"
}이 둘은 같은 줄이 하나도 없지만, 이 도구는 둘 사이에서 어떤 차이도 알리지 않습니다. 멤버도 값도 같고 배열 안의 순서도 같기 때문입니다. 실질적인 결과는 이렇습니다. 비교가 되게 하려고 문서의 서식을 다시 손볼 일이 결코 없습니다. 그렇게 하면 견주려던 바로 그것을 바꾸는 셈이 되니까요.
결코 차이로 치지 않는 것
문서가 어떻게 적혔는지에 관한 네 가지는 무시되며, 조건 없이 무시됩니다. 그중 어느 것도 되살리는 조작기는 없습니다. 그럴 수 있는 도구라면 설명해야 할 뜻이 둘인 도구 두 개가 될 테고, 읽는 사람은 눈앞의 답을 그중 어느 쪽이 냈는지 알아야만 하기 때문입니다.
- 객체의 멤버가 적힌 순서. {"a": 1, "b": 2}와 {"b": 2, "a": 1}은 같은 데이터를 지니므로, 실행할 때마다 키를 다른 순서로 내보내는 직렬화기가 여기서 변경으로 나타나는 일은 없습니다.
- 온갖 종류의 공백 — 들여쓰기, 줄바꿈, 쌍점 뒤의 빈칸. 같은 데이터를 지닌 압축된 문서와 서식을 넣은 문서는 같은 문서가 두 번 있는 것입니다.
- 숫자를 적는 방식. 1e3은 1000이고 1.50은 1.5입니다. JSON의 숫자에는 값이 있을 뿐 철자가 없기 때문이며, 그 점만 다른 두 문서는 같은 숫자를 지니고 그에 대해서는 아무것도 알리지 않습니다.
- 문자열 안의 문자를 이스케이프한 방식. 여섯 글자 \u0041과 글자 A는 한 글자짜리 같은 문자열입니다.
그 목록에 들어갈 법한데 일부러 넣지 않은 것이 둘 있습니다. 배열 원소의 순서는 데이터이고([1, 2]와 [2, 1]은 서로 다른 문서입니다), 값이 null인 멤버는 아예 없는 멤버와 같지 않습니다. 그래서 한쪽과 다른 쪽의 대비는 조용히 넘어가지 않고 알려집니다.
추가됨, 삭제됨, 변경됨 — 그리고 형의 바뀜
결과의 각 행은 정확히 세 갈래 가운데 하나이며, 셋이 함께 비교가 찾아낼 수 있는 모든 것을 덮습니다. 다음 두 문서를 보십시오.
{"host":"api.example.com","port":8080,"debug":true}
{"host":"api.example.com","port":"8080","retries":3}- $['port']에서 변경됨. 멤버가 두 문서에 다 있고 값이 같지 않으므로 두 값이 모두 보입니다. 이 행에는 형이 바뀌었다는 표시도 붙습니다. 8080은 숫자이고 "8080"은 문자열이기 때문입니다.
- $['debug']에서 삭제됨. 멤버가 첫 번째 문서에는 있고 두 번째 문서에는 없습니다.
- $['retries']에서 추가됨. 멤버가 두 번째 문서에는 있고 첫 번째 문서에는 없습니다.
host라는 이름의 멤버는 둘 다에 같은 값으로 있으므로 아예 알려지지 않습니다. 형의 바뀜은 변경의 성질이지 네 번째 갈래의 행이 아닙니다. 스키마는 알아채고 두 파일을 읽는 사람은 대개 알아채지 못하는 어긋남이 그것이므로, 여러분이 찾아내도록 두지 않고 일어난 자리에서 짚어 줍니다.
차이가 놓인 자리를, 경로로 적기
각 행은 자기가 놓인 자리를 이름 붙이며, 그것을 행 번호가 아니라 문서 안으로 들어가는 경로로 이름 붙입니다. 행 번호는 적힌 모양에 관한 사실이고, 그것이야말로 이 도구가 방금 무시하기를 마친 것이니까요. 경로는 RFC 9535 정규화 경로이며, JSON 안의 위치를 적어야 하는 곳이면 어디서나 이 사이트가 쓰는 단 하나의 표기법입니다.
- $는 문서 전체이고, $['port']는 그 안의 port라는 이름의 멤버이며, $['hosts'][1]은 hosts 아래 배열의 색인 1 원소입니다. 멤버는 언제나 대괄호와 따옴표 안에 적히므로, 점이나 빈칸이나 제 나름의 괄호를 품은 이름이라도 따로 손볼 것이 없습니다.
- 경로는 실행할 수 있는 질의입니다. 그것이 속한 문서와 함께 이 사이트의 JSONPath 테스터에 붙여 넣으면 바로 그 노드가 선택되며, 차이를 그 둘레와 함께 읽는 가장 빠른 방법이 그것입니다.
- 그것은 노드가 실제로 들어 있는 쪽 문서에 대한 질의입니다. 추가된 멤버의 경로는 두 번째 문서 위에서 돌고, 삭제된 멤버의 경로는 첫 번째 문서 위에서 돕니다. 여기서는 없는 노드를 이름 붙이는 일이 결코 없습니다.
변경된 행은 경로를 둘 지닐 수 있는데, 그것은 다음 절의 짝짓기가 비쳐 보이는 것입니다. 배열이 원소를 하나 얻거나 잃는 순간, 같은 원소가 양쪽에서 서로 다른 색인에 앉게 됩니다. 두 경로가 같은 곳에서는 — 거의 언제나 그렇습니다만 — 하나만 보입니다.
두 배열을 어떻게 짝짓는가
두 객체는 멤버별로 견주며, 멤버에는 이름이 있으니 그것은 간단합니다. 두 배열에는 이름이 없고 자리만 있는데, 자리별로 견주는 것이야말로 대부분의 비교 결과를 읽을 수 없게 만드는 것입니다. 긴 배열의 맨 앞에 레코드를 하나 끼워 넣으면 이제 무엇도 있던 자리에 없고, 자리를 정체성으로 읽는 비교는 배열 전체를 다르다고 알립니다. 좁은 뜻으로는 참이고 다른 모든 뜻으로는 쓸모가 없습니다. 그래서 원소를 먼저 짝지읍니다. 여러분이 지목하는 항목이 아니라 원소가 무엇인지에 따라서 말입니다. 그리고 짝짓기가 남긴 것만 알립니다.
{"hosts": ["alpha", "beta", "gamma"]}
{"hosts": ["alpha", "staging", "beta", "gamma"]}이것은 한 행입니다. staging이 $['hosts'][1]에 추가되었습니다. beta와 gamma라는 원소는 한 칸씩 밀렸을 뿐이라 언급되지 않습니다. 움직이는 것은 바뀌는 것이 아니니까요. 배열의 한 항목 안에서 고쳐진 한 필드가, 항목 전체가 다른 것으로 갈렸다는 식이 아니라 그 필드에서의 변경으로 알려지게 하는 것도 같은 짝짓기입니다.
순서는 여전히 셈에 들어가고, 짝짓기도 아닌 척하지 않습니다. [1, 2]와 [2, 1]은 앞에서 1이 삭제되고 2 뒤에 1이 추가된 것으로 돌아옵니다. 실제로 일어난 일이 그것입니다. 두 배열이 짝짓기가 비용에 값하지 않을 만큼 서로 다를 수도 있는데, 그 점을 넘어서면 비교는 자리별로 훑는 방식으로 물러나고 그것을 결과의 맨 위에서 말합니다. 그래서 시끄러운 답이 알 수 없는 것이 아니라 설명된 것이 됩니다.
보고서와 트리
같은 비교가 두 가지 보임새로 주어지며, 그 사이를 오가도 다시 계산되는 것은 없습니다. 트리는 보고서가 늘어놓는 바로 그 차이 목록에서 그려지므로, 무엇이 바뀌었는지에 대해서도 얼마나 있는지에 대해서도 둘이 어긋날 수 없습니다.
- 보고서는 무엇이 바뀌었는가에 답합니다. 차이마다 한 행이고, 저마다 경로와 갈래와 양쪽의 값을 지닙니다. 목록 전체를 앞에 펼쳐 두고 훑고 싶을 때 보는 보임새입니다.
- 트리는 문서의 어디인가에 답합니다. 두 문서를 하나의 얼개로 녹이고 차이를 지닌 부분만 펼쳐 둔 것입니다. 아무것도 지니지 않은 자식이 잇달아 놓인 구간마다 몇 개를 대신하는지 말하는 한 행으로 접힙니다. 위 절의 짝은 다섯 행으로 그려집니다. 문서, 그 안의 배열, 원소 하나를 대신하는 접힌 행, 추가된 원소, 그리고 둘을 대신하는 접힌 행입니다.
- 결과 제목 옆의 개수는 있는 차이 전부입니다. 화면의 목록이 길이 때문에 잘려도 그 개수는 움직이지 않고, 목록 발치의 조작기가 나머지를 보여 줍니다.
~! $['port'] 8080 -> "8080" - $['debug'] true + $['retries'] 3
세 번째 절의 두 문서에 대해 복사 조작기가 내놓는 것이 이것입니다. 갈래를 나타내는 표시, 이어서 경로, 이어서 화살표를 사이에 둔 값들 — 추가된 멤버에는 더하기, 삭제된 멤버에는 빼기, 변경에는 물결표, 형까지 바뀐 곳에는 물결표와 느낌표입니다. 낱말이 아니라 기호로 적힌 것은 일부러 그런 것입니다. 붙여 넣은 결과가 사이트의 어느 언어로 읽고 있었든 같은 텍스트가 되도록 하기 위해서입니다. 그리고 아무것도 줄이지 않습니다. 화면이 잘라 낸 값도 그 안에는 온전히 들어 있습니다.
구문 분석의 대가와, 도구가 소리 내어 말하는 것
두 문서가 구문 분석된 결과를 견준다는 것은 그 분석의 대가를 안고 간다는 뜻이며, JSON을 구문 분석하는 일은 손실이 없지 않습니다. 그것이 이 사이트의 어느 곳보다 여기서 무거운 까닭은, 비교 도구가 가장 감당할 수 없는 답이 실제로는 다른 두 문서에 대한 “차이 없음”이기 때문입니다. 그래서 각 창의 텍스트를 텍스트로서 한 번 더 읽고, 분석이 떨어뜨린 것을 삼키는 대신 비교 곁에서 알립니다.
- 같은 객체 안에 두 번 적힌 멤버 이름. 구문 분석에서 살아남는 것은 나중 것뿐이므로 견주어진 것도 나중 것뿐이고, 먼저 것은 아무도 보지 못했습니다.
- 배정밀도로 살아남기에는 너무 긴 숫자. 서로 다른 두 표기가 같은 값으로 분석될 수 있는데, 식별자가 바로 그런 일이 벌어지는 자리입니다. 12345678901234567890과 12345678901234567891은 서로 다른 정수이면서 분석되고 나면 한 숫자이므로, 비교 혼자서는 식별자가 다른 두 문서를 같다고 부르게 됩니다.
{"user": {"id": 1}, "user": {"id": 2}}저 문서는 {"user": {"id": 2}}로 분석되며, 도구는 그것이 붙여 넣어진 창 아래에서, 첫 사례의 행과 열 그리고 모두 몇 건인지와 함께 그렇게 말합니다. 두 손실 가운데 어느 것도 비교를 멈추지 않고, 둘 다 비교 곁에 놓입니다. 아예 분석되지 않는 문서도 같은 자리에서 알려지며, 줄 만한 위치가 있는 한 문제의 위치도 함께 나옵니다. 두 창은 서로 따로 읽히므로, 망가진 문서가 둘이면 하나 뒤에 하나가 아니라 오류가 한꺼번에 둘 나옵니다. 값을 그릴 수 있는 깊이보다 훨씬 깊게 중첩된 문서는 그 자리에서 거절됩니다. 그것은 거절이지 멈춰 버린 탭이 아닙니다.
붙여 넣은 것이 이 탭을 떠나지 않는 까닭
두 문서 모두 여러분의 브라우저 안에 머무릅니다. 업로드도 요청도 없고, 사본을 지닐 수 있는 서버도 없습니다. 비교는 이미 불러 놓은 페이지 안에서 도는 산술이며, 네트워크를 꺼도 계속 동작하는 까닭도 그것입니다. 운영 환경의 응답이나 고객 기록이나 서명된 페이로드를 여기에 붙여 넣어도 안전한 까닭이 바로 그것입니다.
저장되는 것도 없습니다. 페이지를 다시 불러오면 두 창 모두 비어 있습니다. 기록도 계정도 없고, 나중에 지울 것도 없습니다. 여기서 나가는 것은 여러분이 스스로 복사한 것뿐입니다.
자주 묻는 질문
- 이 도구는 키 순서를 무시하나요?
- 네, 언제나 그렇고, 도구가 있는 까닭이 바로 그것입니다. 같은 멤버를 같은 값으로 지닌 두 객체는 어떻게 적혔든 같으므로, 실행할 때마다 키를 다른 순서로 내보내는 직렬화기가 변경으로 나타나는 일은 없습니다. 들여쓰기, 압축, 숫자를 적는 방식, 문자를 이스케이프한 방식이 무시되는 것도 같은 까닭이며, 그중 어느 것도 여러분이 반대로 돌려놓을 수 있었던 설정이 아닙니다.
- null로 놓인 멤버와 아예 없는 멤버는 같은가요?
- 아니요, 그리고 둘을 같게 다루는 선택지도 없습니다. {"note": null}과 {}의 비교는 $['note'] 삭제됨으로 알려집니다. 있으면서 비어 있는 필드는 아무도 보내지 않은 필드와 다른 진술입니다. 모든 스키마 언어와 정적 형을 지닌 모든 언어가 둘을 갈라 보므로, 여기서 뭉뚱그리면 문서가 실제로 말하고 있는 것을 버리는 셈이 됩니다.
- [1, 2]와 [2, 1]은 같다고 알려지나요?
- 아니요. JSON 배열은 순서가 있으므로, 같은 원소를 다른 순서로 지닌 두 배열은 서로 다른 문서이고, 그것을 같다고 부르면 이 도구가 형식에 대해 거짓을 말하는 셈이 됩니다. 여러분이 얻는 것은 삭제 하나와 추가 하나입니다. 1이 앞에서 삭제되고 2 뒤에 다시 추가되었습니다. 객체는 그 반대인데, 그 멤버는 자리가 아니라 이름으로 가리켜지기 때문입니다.
- 각 행의 경로는 무슨 뜻인가요?
- 차이가 문서 안 어디에 놓였는지를 RFC 9535 정규화 경로로 적은 것입니다. $는 문서 그 자체, $['port']는 그 멤버 하나, $['hosts'][1]은 hosts 아래 배열의 색인 1 원소입니다. 실행할 수 있는 질의이기도 합니다. 그것이 속한 문서와 함께 이 사이트의 JSONPath 테스터에 붙여 넣으면 바로 그 노드만 선택됩니다.
- 어떤 행이 서로 다른 경로 둘을 보인 까닭은 무엇인가요?
- 두 배열을 짝짓다 보면 같은 원소가 양쪽에서 서로 다른 색인에 남을 수 있기 때문입니다. ["alpha", "beta"]와 ["intro", "alpha", "beta!"]를 견주면 두 행이 나옵니다. intro가 $[0]에 추가되었고, beta가 beta!로 변경되었는데 그것은 첫 번째 문서에서는 $[1]이고 두 번째 문서에서는 $[2]입니다. 두 경로가 같은 곳에서는, 그리고 대개 같습니다만, 하나만 보입니다.
- 행에 붙은 형의 바뀜은 무슨 뜻인가요?
- 값이 그저 다른 것이 아니라 다른 갈래의 것이 되었다는 뜻입니다. 숫자가 문자열이 되었거나, 값이 null이 되었거나, 객체가 배열이 되었거나 하는 식입니다. 한쪽에는 8080, 다른 쪽에는 "8080"으로 적힌 포트가 가장 흔한 경우이며, 대개는 데이터가 아니라 직렬화기나 클라이언트가 바뀌었다는 뜻입니다. 행에 표시되는 까닭은 고쳐진 값과 어긋나 가는 약속이 여러분에게 서로 다른 대응을 요구하기 때문입니다.
- 두 문서가 똑같아 보이는데 한쪽이 같은 키를 두 번 적었습니다. 어떻게 되나요?
- 구문 분석은 나중 것을 남기고 먼저 것을 떨어뜨리므로, 비교는 멤버 하나만 보게 되고 차이가 없다고 알릴 수도 충분히 있습니다. 도구가 바로 그 때문에 날 텍스트를 따로 읽고, 그 창 아래에서 이름이 두 번 적혔다는 것과 모두 몇 번인지와 첫 번째가 어디인지를 말합니다. 그 같은 두 번째 읽기가 배정밀도로 살아남기에는 너무 긴 정수도 잡아냅니다. 서로 다른 두 문서가 다르지 않은 둘로 분석될 수 있는 또 하나의 길이 그것입니다.
- 적용할 수 있는 패치를 받을 수 있나요?
- 아니요, 그리고 그것은 빠진 것이 아니라 정한 것입니다. JSON 패치는 연산을 하나씩 차례로 적용하므로 그 안의 색인이 도는 동안 밀립니다. 그런 것을 내놓는다는 것은 여러분이 자기 데이터에 대해 돌릴 프로그램에 관한 약속이며, 무엇이 다른지를 적어 주는 것보다 훨씬 큰 주장입니다. 대신 가져갈 수 있는 것은 복사 조작기에서 얻는 텍스트 보고서입니다. 사이트의 모든 언어에서 같고, 어디에서도 줄이지 않았습니다.
- 제가 붙여 넣은 것이 서버로 보내지나요?
- 아니요. 두 문서는 여러분의 브라우저 안에서 견주어지고 어느 것도 그곳을 떠나지 않습니다. 업로드도 요청도 없고, 방문 사이에 남는 것도 없습니다. 운영 환경의 응답을 붙여 넣어도 안전한 까닭이 그것이고, 네트워크를 꺼도 도구가 계속 동작하는 까닭도 그것입니다. 페이지를 다시 불러오면 두 창은 다시 비어 있습니다.