한국어

개발자 도구 · JSON 포맷터 및 유효성 검사기

JSON에서 키 순서가 중요합니까? 순서, 동등 및 RFC 8785

· 배경

JSON 표준 검증

JSON에서 키 순서가 중요합니까? JSON 토큰과 정확한 검증 경계로 설명된 순서, 동등성 및 RFC 8785
원본 ToolAcre 벡터 일러스트레이션

JSON 사양은 개체를 순서 없이 호출하지만 실제 파서와 직렬 변환기는 일반적으로 순서를 유지하고 서명 체계는 이에 따라 달라집니다. 이 게시물에서는 사양의 내용, 구현의 기능, 정규화가 긴장을 해결하는 방법을 설명합니다.

동일한 데이터, 다른 바이트

`{"city":"Oslo","temp":4}` 및 `{"temp":4,"city":"Oslo"}`에는 동일한 두 이름과 값이 포함되어 있지만 소스 바이트는 다릅니다. 들여쓰기는 구문 분석된 값을 변경하지 않고도 더 많은 텍스트 차이를 추가할 수 있습니다. 이것이 바로 "equal JSON"에 비교 규칙이 필요한 이유입니다. 텍스트, 구문 분석된 개체 또는 다른 프로토콜에 정의된 표준 표현을 비교하고 있습니까?

ToolAcre는 동일한 들여쓰기로 두 문서의 형식을 지정하여 공백 노이즈를 제거할 수 있습니다. 해당 옵션을 선택하면 객체 키를 재귀적으로 정렬할 수도 있습니다. 정렬은 멤버 순서를 의도적으로 변경하지만 배열 위치는 데이터를 나타내기 때문에 배열 요소를 이동하지 않습니다. 일반적인 형식이나 이 선택적 정렬은 RFC 8785 정식 JSON을 생성하지 않으므로 출력이 지정된 서명 형식으로 대체되어서는 안 됩니다.

RFC 8259의 내용 — 객체는 name/value 쌍의 정렬되지 않은 컬렉션이며 구현은 순서를 노출할지 여부를 나타낼 수 있습니다.

RFC 8259는 개체를 name/value 쌍의 순서 없는 컬렉션으로 설명합니다. 따라서 멤버 순서를 일반 JSON 개체의 의미로 처리하는 소프트웨어는 해당 추상 모델 외부의 동작에 의존합니다. 배열은 명시적으로 순서가 지정되므로 `["draft","final"]`은 `["final","draft"]`와 교환할 수 없습니다. 객체 순서와 배열 순서는 동일한 규칙으로 정규화되어서는 안 됩니다.

또한 RFC는 라이브러리가 호출자에게 멤버 순서를 공개하는지 여부가 다르다는 점을 지적합니다. 이 경고는 이식 가능한 디자인에 충분합니다. 한 객체 멤버를 다른 객체 앞에 배치하여 우선 순위나 순서를 인코딩하지 마십시오. 순서가 중요한 경우 배열이나 명시적 필드로 표현하세요. 안정된 순서를 보여주는 포맷터는 인간에게는 편리하지만 위치를 객체의 표준 수준 속성으로 변환하지는 않습니다.

이 포맷터가 실제로 수행하는 작업

정렬이 비활성화되면 ToolAcre는 문서를 구문 분석하고 결과 JavaScript 값을 직렬화합니다. 출력은 원래 토큰 스트림 바이트를 바이트 단위로 유지하는 대신 JavaScript 속성 열거 동작을 따릅니다. 대부분의 일반 문자열 키는 익숙한 순서로 표시되는 반면, 정수 인덱스와 유사한 이름은 다른 이름보다 먼저 생성될 수 있습니다. 숫자 철자와 이스케이프 선택도 재직렬화 중에 정규화될 수 있습니다.

정렬이 활성화되면 포맷터는 모든 중첩 개체에서 자체 키가 알파벳순으로 정렬된 새 개체를 만듭니다. `{"z":{"b":1,"a":2},"items":[{"d":4,"c":3},"x"]}`의 경우 개체 이름은 `items`, `z`가 됩니다. 중첩된 개체 이름도 정렬됩니다. 배열에는 여전히 `"x"` 이전의 개체가 포함되어 있습니다. 배열 내부의 객체를 정렬한다고 해서 배열 자체를 정렬하는 것은 아닙니다.

바이트 순서가 중요한 경우

프로세스가 추상 값이 아닌 정확한 바이트를 사용할 때마다 텍스트 순서가 중요합니다. 멤버가 이동하거나 공백이 변경되면 파일 해시, 캐시 키, 디지털 서명 또는 라인 기반 차이점이 변경됩니다. 이는 순서가 지정되지 않은 개체 모델과 모순되지 않습니다. 이는 주변 프로세스가 입력의 일부로 바이트 표현을 선택했음을 의미합니다. 표현 규칙은 명시적이고 공유되어야 합니다.

일상적인 검토의 경우 일관된 들여쓰기 및 선택적인 알파벳순 정렬을 통해 변경 사항을 더 쉽게 확인할 수 있습니다. 암호화 또는 프로토콜 작업의 경우 "안정적으로 보인다"는 것은 계약이 아닙니다. 생산자와 검증자는 해시 또는 서명 전에 프로토콜에서 요구하는 정확한 정규화 알고리즘을 사용해야 합니다. 알고리즘 이름이 지정되지 않은 경우 ToolAcre의 출력이 버전, 런타임 또는 엣지 케이스 값에 걸쳐 다른 직렬 변환기와 일치할 것이라고 가정하지 마십시오.

키 정렬이 RFC가 아닌 이유 8785

RFC 8785는 호환 가능한 데이터에서 반복 가능한 바이트를 생성하기 위한 JSON 정규화 체계를 정의합니다. 그 작업은 키를 알파벳 순서로 배치하는 것보다 더 광범위합니다. 문자열 및 숫자에 대한 정확한 직렬화 동작과 함께 결정적 속성 정렬을 지정하고 입력 모델에 제약 조건을 적용합니다. 예쁜 들여쓰기는 표준 출력의 일부가 아니며 로케일 인식 정렬은 허용되는 근사치가 아닙니다.

ToolAcre는 RFC 8785 클레임을 하지 않습니다. 정렬 옵션은 `JSON.parse` 및 `JSON.stringify`에 계층화된 가독성 기능입니다. I-JSON 전제조건을 검증하지 않거나 RFC의 직렬화 규칙을 대체하지 않습니다. `1e-7`와 같은 값, ASCII가 아닌 문자를 포함하는 키 또는 이스케이프된 문자열은 일반 정렬 포맷터와 적합한 정규화기 간의 차이점을 드러낼 수 있습니다. JCS가 필요한 경우 테스트된 JCS 구현을 사용하십시오.

실제 사례: 두 문서를 공정하게 비교

`{"meta":{"rev":2,"owner":"Mira"},"steps":["cut","pack"]}`을(를) `{"steps":["cut","pack"],"meta":{"owner":"Mira","rev":2}}`과 비교하세요. 두 개의 공백과 정렬이 비활성화된 형식 모두: 공백은 일관되지만 루트 및 중첩 멤버 순서는 여전히 다를 수 있습니다. 원시 텍스트를 동일하다고 선언하는 대신 두 가지를 모두 구문 분석하고 의도한 필드를 비교하여 값 수준 동등성을 설정합니다.

재귀 키 정렬을 켜면 두 예제 모두 동일한 객체 순서로 렌더링되고 `steps`은 `cut`, 그 다음에는 `pack`로 유지됩니다. 이는 인간 비교에 유용하지만 여전히 RFC 8785 증명이 아닌 ToolAcre의 정규화입니다. 두 번째 배열이 `["pack","cut"]`인 경우 배열을 변경하면 표시된 순서가 변경되므로 키를 정렬하면 해당 차이가 올바르게 표시됩니다.

여기서 다루지 않는 내용

키 정렬은 모든 애플리케이션에 대해 깊은 동등성을 정의하지 않습니다. `JSON.parse`에서는 중복된 이름을 허용하여 마지막 값을 유지하므로 서식을 지정하면 한 소스에 반복 항목이 포함되어 있다는 증거가 삭제될 수 있습니다. 큰 정수는 이미 JavaScript 값의 정밀도를 잃었을 수 있습니다. 도메인은 선택된 배열을 세트로 처리할 수도 있지만 ToolAcre는 해당 규칙을 추론할 수 없으므로 배열을 재정렬하지 않습니다.

포맷터는 또한 스키마를 비교하거나, 기본값을 적용하거나, 유니코드를 정규화하거나, 두 숫자 표현이 다운스트림 시스템에 허용되는지 여부를 결정하지 않습니다. 그것들은 별도의 계약입니다. 서식을 사용하여 프레젠테이션 노이즈를 줄이고, 값 동일성을 위해 특별히 설계된 구조적 비교를 사용하고, 정확한 바이트를 위해 지정된 정규화기를 사용합니다. "정규화"라는 단어 아래 이러한 작업을 혼합하면 실제로 비교된 내용에 대한 잘못된 신뢰가 생성됩니다.

요점: 순서는 모델에는 중요하지 않지만 바이트에는 중요합니다.

개체 멤버 순서는 RFC 8259 데이터 모델에서 의미를 전달하지 않지만 배열 순서는 의미를 갖습니다. 소스 바이트는 여전히 순서와 공백을 모두 기록하므로 해시, 서명 및 텍스트 차이점은 값 지향 비교에서 무시할 수 있는 구별을 관찰합니다. 도구를 선택하기 전에 어떤 계층이 중요한지 명시하십시오. 텍스트 ID, 구문 분석 값 동등성 및 프로토콜 정의 표준 ID는 세 가지 다른 질문입니다.

ToolAcre는 처음 두 작업 흐름을 간접적으로만 지원합니다. 일관된 형식은 텍스트 차이를 명확하게 하고 재귀적인 알파벳순 개체 키 정렬을 통해 사람이 더 조용하게 비교할 수 있습니다. 배열은 정렬되지 않습니다. 결과는 RFC 8785 표준 JSON이 아니므로 마치 서명된 것처럼 서명해서는 안 됩니다. 어휘 증거가 중요한 경우 원래 입력을 보존하십시오. 특히 중복 키를 구문 분석하면 마지막 값만 유지되기 때문입니다.