[json] JSON 구문은 객체에서 중복 키를 허용합니까?

이것은 유효한 JSON입니까?

{
    "a" : "x",
    "a" : "y"
}

http://jsonlint.com/에서 예라고 말합니다.

http://www.json.org/ 는 금지 된 내용에 대해 아무 말도하지 않습니다.

그러나 분명히 이해가되지 않습니까? 대부분의 구현은 아마도 해시 테이블을 사용하므로 어쨌든 재정의됩니다.



답변

에서 표준 (P II.) :

다른 표준은이 표준을 참조하여 JSON 텍스트 형식을 엄격하게 준수하면서 다양한 인코딩 세부 사항에 제한을 가할 것으로 예상됩니다. 이러한 표준은 특정 행동을 요구할 수 있습니다. JSON 자체는 동작을 지정하지 않습니다.

표준 (p. 2)에서 JSON 객체의 사양은 다음과 같습니다.

오브젝트 구조는 0 개 이상의 이름 / 값 쌍을 둘러싼 중괄호 토큰 쌍으로 표시됩니다. 이름은 문자열입니다. 단일 콜론 토큰은 이름과 값을 구분하여 각 이름 뒤에옵니다. 단일 쉼표 토큰은 다음 이름과 값을 구분합니다.

JSON 객체 다이어그램

중복 키가 유효하지 않거나 유효한 것은 언급하지 않았으므로 사양에 따라 안전하게 허용된다고 가정합니다.

JSON 라이브러리의 대부분의 구현은 할 수 없습니다 때문에 첫 번째 인용문의 표준으로하지 않습니다 충돌 중복 키에 동의합니다.

다음은 C ++ 표준 라이브러리와 관련된 두 가지 예입니다. 일부 JSON 객체를 직렬화 해제하면 std::map중복 키를 거부 하는 것이 좋습니다. 그러나 일부 JSON 객체를 직렬화 해제하면 std::multimap복제 키를 정상적으로 받아들이는 것이 좋습니다.


답변

짧은 대답 : 예, 권장하지 않습니다.

긴 대답 : 그것은 당신이 유효한 전화에 달려 있습니다 …

ECMA-404 “JSON 데이터 교환 구문”은 중복 된 이름 (키)에 대해 아무 말도하지 않습니다.

그러나 RFC 8259 “JSON (JavaScript Object Notation) 데이터 교환 형식”은 다음과 같이 말합니다.

객체 내 이름은 고유해야합니다.

이러한 맥락에서 SHOULD 에서 지정하는 것으로 이해되어야한다 BCP 14 :

SHOULD 이 단어, 또는 형용사 “권장”는이 특정 항목을 무시하고 특정 상황에서 유효한 이유가있을 수 있지만, 전체 의미가 이해되어야 조심스럽게 다른 과정을 선택하기 전에 무게 것을 의미한다.

RFC 8259 는 고유 이름 (키)이 좋은 이유를 설명합니다.

이름이 모두 고유 한 객체는 해당 객체를받는 모든 소프트웨어 구현이 이름-값 매핑에 동의한다는 의미에서 상호 운용이 가능합니다. 개체 내에서 이름이 고유하지 않으면 해당 개체를받는 소프트웨어의 동작을 예측할 수 없습니다. 많은 구현에서 성 / 값 쌍만보고합니다. 다른 구현에서는 오류를보고하거나 개체를 구문 분석하지 못하고 일부 구현에서는 중복을 포함하여 모든 이름 / 값 쌍을보고합니다.


또한 Serguei가 ECMA-262 “ECMAScript® 언어 사양” 이라는 의견에서 지적한대로 다음과 같이 읽습니다.

객체 내에 중복 된 이름 문자열이있는 경우 동일한 키에 대한 사 전적으로 선행하는 값을 덮어 씁니다.

다시 말해, 마지막 가치는 이깁니다.


Douglas Crockford (JSON 제작자)가 Java 구현으로 이름이 중복 된 문자열을 구문 분석하려고 하면 예외가 발생합니다 .

org.json.JSONException: Duplicate key "status"  at
org.json.JSONObject.putOnce(JSONObject.java:1076)


답변

JSON 형식을 지정하는 2 개의 문서가 있습니다.

  1. http://json.org/
  2. https://tools.ietf.org/html/rfc7159

수락 된 답변은 첫 번째 문서에서 인용됩니다. 첫 번째 문서가 더 명확하다고 생각하지만 두 번째 문서에 더 자세한 내용이 포함되어 있습니다.

두 번째 문서는 다음과 같이 말합니다.

  1. 사물

    객체 구조는 0 개 이상의 이름 / 값 쌍 (또는 멤버)을 둘러싸는 중괄호 쌍으로 표시됩니다. 이름은 문자열입니다. 각 이름 뒤에 단일 콜론이 나타나 이름과 값을 구분합니다. 단일 쉼표는 다음 이름과 값을 구분합니다. 객체 내 이름은 고유해야합니다.

따라서 중복 이름을 사용하는 것은 금지되어 있지만 권장하지는 않습니다.


답변

XML과 JSON을 모두 허용하는 API를 처리 할 때 비슷한 질문을 받았지만 JSON에서 중복 키가 될 것으로 예상되는 것을 처리하는 방법을 문서화하지 않았습니다.

다음은 샘플 JSON의 유효한 XML 표현입니다.

<object>
  <a>x</a>
  <a>y</a>
</object>

이것이 JSON으로 변환되면 다음과 같은 결과가 나타납니다.

{
  "object": {
    "a": [
      "x",
      "y"
    ]
  }
}

중복 키라고하는 것을 처리하는 언어를 다른 언어로 자연스럽게 매핑하면 여기에서 잠재적 인 모범 사례 참조가 될 수 있습니다.

누군가를 돕는 희망!


답변

JSON 사양은 다음과 같이 말합니다.

객체는 정렬되지 않은 이름 / 값 쌍 세트입니다.

여기서 중요한 부분은 “정렬되지 않은”것입니다. 특정 쌍을 참조하는 데 사용할 수있는 유일한 것은 키이기 때문에 키의 고유성을 의미합니다.

또한 대부분의 JSON 라이브러리는 JSON 객체를 역 직렬화하여 키가 고유하게 보장되는지도 / 사전을 해시합니다. 중복 키를 사용하여 JSON 객체를 직렬화 해제하는 경우 라이브러리에 따라 달라집니다. 대부분의 경우 오류가 발생하거나 각 중복 키의 마지막 값만 고려됩니다.

예를 들어 Python에서는을 json.loads('{"a": 1, "a": 2}')반환합니다 {"a": 2}.


답변

고유해야한다는 것이 반드시 고유해야한다는 의미는 아닙니다. 그러나 언급했듯이 일부 파서는 실패하고 다른 파서는 마지막으로 구문 분석 된 값을 사용합니다. 그러나 스펙이 중복을 허용하도록 약간 정리 된 경우 JSON을 HTML 또는 다른 형식으로 변환하는 이벤트 핸들러가있는 사용을 볼 수 있습니다 …이 경우 완벽하게 유효합니다. JSON을 구문 분석하고 다른 문서 형식을 작성하십시오 …

[
  "div":
  {
    "p":"hello",
    "p":"universe"
  }
  "div":
  {
    "h1":"Heading 1",
    "p":"another paragraph"
  }
]

그런 다음 예를 들어 html로 쉽게 파싱 할 수 있습니다.

<body>
 <div>
  <p>hello</p>
  <p>universe</p>
 </div>
 <div>
  <h1>Heading 1</h1>
  <p>another paragraph</p>
 </div>
</body>

나는 그 질문에 대한 추론을 볼 수 있지만 그것이 서있는 것처럼 … 나는 그것을 믿지 않을 것입니다.


답변

목적을 요구하면 다른 답변이 있습니다.

JSON을 사용하여 객체를 직렬화 (JavaScriptObjectNotation)하면 각 사전 요소가 개별 객체 속성에 매핑되므로 동일한 속성에 대한 값을 정의하는 다른 항목은 의미가 없습니다.

그러나 API 테스트를 위해 JSON 샘플을 작성하는 매우 구체적인 사용 사례에서 같은 질문을 받았습니다. 유용성을 손상시키지 않고 JSON 파일에 주석을 추가하는 방법이 궁금했습니다. JSON 사양은 주석을 모르므로 매우 간단한 접근법을 생각해 냈습니다.

중복 키를 사용하여 JSON 샘플에 주석을 답니다 . 예:

{
"property1" : "value1", "REMARK" : "... prop1 controls ...",
"property2" : "value2", "REMARK" : "... value2 raises an exception ...",
}

우리가 사용하는 JSON 시리얼 라이저는 이러한 “REMARK”복제본에 문제가 없으며 애플리케이션 코드는이 작은 오버 헤드를 무시합니다.

따라서 애플리케이션 계층에는 아무런 의미가 없지만 이러한 중복은 JSON의 유용성을 손상시키지 않고 테스트 샘플에 주석을 추가하는 유용한 해결 방법을 제공합니다.