이것은 유효한 JSON입니까?
{
"a" : "x",
"a" : "y"
}
http://jsonlint.com/에서 예라고 말합니다.
http://www.json.org/ 는 금지 된 내용에 대해 아무 말도하지 않습니다.
그러나 분명히 이해가되지 않습니까? 대부분의 구현은 아마도 해시 테이블을 사용하므로 어쨌든 재정의됩니다.
이것은 유효한 JSON입니까?
{
"a" : "x",
"a" : "y"
}
http://jsonlint.com/에서 예라고 말합니다.
http://www.json.org/ 는 금지 된 내용에 대해 아무 말도하지 않습니다.
그러나 분명히 이해가되지 않습니까? 대부분의 구현은 아마도 해시 테이블을 사용하므로 어쨌든 재정의됩니다.
답변:
에서 표준 (P II.) :
다른 표준은이 표준을 참조하여 JSON 텍스트 형식을 엄격하게 준수하면서 다양한 인코딩 세부 사항에 제한을 가할 것으로 예상됩니다. 이러한 표준은 특정 행동을 요구할 수 있습니다. JSON 자체는 동작을 지정하지 않습니다.
표준 (p. 2)에서 JSON 객체의 사양은 다음과 같습니다.
오브젝트 구조는 0 개 이상의 이름 / 값 쌍을 둘러싼 중괄호 토큰 쌍으로 표시됩니다. 이름은 문자열입니다. 단일 콜론 토큰은 이름과 값을 구분하여 각 이름 뒤에옵니다. 단일 쉼표 토큰은 다음 이름과 값을 구분합니다.
중복 키가 유효하지 않거나 유효한 것은 언급하지 않았으므로 사양에 따라 안전하게 허용된다고 가정합니다.
JSON 라이브러리의 대부분의 구현은 할 수 없습니다 때문에 첫 번째 인용문의 표준으로하지 않습니다 충돌 중복 키에 동의합니다.
다음은 C ++ 표준 라이브러리와 관련된 두 가지 예입니다. 일부 JSON 객체를 직렬화 해제하면 std::map
중복 키를 거부 하는 것이 좋습니다. 그러나 일부 JSON 객체를 직렬화 해제하면 std::multimap
복제 키를 정상적으로 받아들이는 것이 좋습니다.
std::multimap
방금 추가 한 예를 고려하십시오 . 잠재적으로 중복 키가있는 JSON 객체로 직렬화 할 수 있습니다.
{"a":1,"a":2}
두 개의 고유 한 키 / 값 쌍 세트입니다. 실제로 {"a":1,"a":1}
하나의 요소 만 갖는 일련의 키 / 값 쌍으로 생각할 수도 있습니다. 그것이 반복된다는 사실은 단지 구문상의 기발한 것으로 생각할 수 있습니다. 더 나은 정의는 "객체는 문자열 (이름)에서 값까지 부분 함수입니다."
짧은 대답 : 예, 권장하지 않습니다.
긴 대답 : 그것은 당신이 유효한 전화에 달려 있습니다 ...
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)
d8 -e 'x={"a":1,"a":2}; print(x.a);'
이것은 2. 인쇄
JSON.parse()
명시 적으로 말합니다 In the case where there are duplicate name Strings within an object, lexically preceding values for the same key shall be overwritten.
(즉, 최종 가치 승).
JSON 형식을 지정하는 2 개의 문서가 있습니다.
수락 된 답변은 첫 번째 문서에서 인용됩니다. 첫 번째 문서가 더 명확하다고 생각하지만 두 번째 문서에 더 자세한 내용이 포함되어 있습니다.
두 번째 문서는 다음과 같이 말합니다.
사물
객체 구조는 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}
.
{ (a,b), (a,c) }
이다 독특한 세트. 따라서 기술적으로 json.org 정의 {"a":1,"a":2}
는 유효하지만 유효 {"a":1,"a":2,"a":1}
하지 않습니다. 또한 ECMA-404 (실제 표준)는 "set"이라는 단어를 사용하지 않습니다.An object structure is represented as a pair of curly bracket tokens surrounding zero or more name/value pairs.
고유해야한다는 것이 반드시 고유해야한다는 의미는 아닙니다. 그러나 언급했듯이 일부 파서는 실패하고 다른 파서는 마지막으로 구문 분석 된 값을 사용합니다. 그러나 스펙이 중복을 허용하도록 약간 정리 된 경우 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>
나는 그 질문에 대한 추론을 볼 수 있지만 그것이 서있는 것처럼 ... 나는 그것을 믿지 않을 것입니다.
{"div":{"p":"hello","p":"universe"}, "div":{"h1":"Heading 1","p":"another paragraph"}}
. 이제 많은 사람들과 프레임 워크가 JSON 객체를 정렬되지 않은 사전으로 취급하지만 JavaScript 및 MongoDB의 API는 사전 내의 키 순서에 의존하므로 제안하는 (순서 사전)은 들어 본 적이 없습니다. 당신은 특별한 파서가 필요합니다.
목적을 요구하면 다른 답변이 있습니다.
JSON을 사용하여 객체를 직렬화 (JavaScriptObjectNotation)하면 각 사전 요소가 개별 객체 속성에 매핑되므로 동일한 속성에 대한 값을 정의하는 다른 항목은 의미가 없습니다.
그러나 API 테스트를 위해 JSON 샘플을 작성하는 매우 구체적인 사용 사례에서 같은 질문을 받았습니다. 유용성을 손상시키지 않고 JSON 파일에 주석을 추가하는 방법이 궁금했습니다. JSON 사양은 주석을 모르므로 매우 간단한 접근법을 생각해 냈습니다.
중복 키를 사용하여 JSON 샘플에 주석을 답니다 . 예:
{
"property1" : "value1", "REMARK" : "... prop1 controls ...",
"property2" : "value2", "REMARK" : "... value2 raises an exception ...",
}
우리가 사용하는 JSON 시리얼 라이저는 이러한 "REMARK"복제본에 문제가 없으며 애플리케이션 코드는이 작은 오버 헤드를 무시합니다.
따라서 애플리케이션 계층에는 아무런 의미가 없지만 이러한 중복은 JSON의 유용성을 손상시키지 않고 테스트 샘플에 주석을 추가하는 유용한 해결 방법을 제공합니다.
표준에 대한 오래된 아이디어와 혼란이 많기 때문에 게시하고 답변하십시오. 2017 년 12 월 현재 두 가지 경쟁 표준이 있습니다.
RFC 8259- https: //tools.ietf.org/html/rfc8259
ECMA-404- http: //www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
json.org는 ECMA-404는 제안 표준하지만,이 사이트는 권위로 표시되지 않습니다. ECMA를 권위로 간주하는 것이 공정하다고 생각하지만 여기서 중요한 점은 표준 (유일 키에 관한)의 유일한 차이점은 RFC 8259는 키 가 고유 해야 하며 ECMA-404는 필요하지 않다는 것입니다. 독특한.
RFC-8259 :
"객체 내의 이름은 고유해야합니다."
이와 같이 모든 대문자로 "해야한다"라는 단어는 RFC 세계 내에서 의미가 있으며, 이는 다른 표준 (BCP 14, RFC 2119- https: //tools.ietf.org/html/rfc2119)에 구체적으로 정의되어 있습니다.
- SHOULD이 단어 또는 형용사 "RECOMMENDED"는 특정 상황에서 특정 항목을 무시해야하는 유효한 이유가있을 수 있지만 다른 과정을 선택하기 전에 전체적인 의미를 이해하고 신중하게 고려해야합니다.
ECMA-404 :
"JSON 구문은 이름으로 사용되는 문자열에 제한을 두지 않으며 이름 문자열을 고유하게 요구하지 않으며 이름 / 값 쌍의 순서에 의미를 부여하지 않습니다."
따라서 슬라이스 방법에 관계없이 구문 상 유효한 JSON 입니다.
RFC 8259의 고유 한 키 권장 사항은 다음과 같습니다.
이름이 모두 고유 한 객체는 해당 객체를받는 모든 소프트웨어 구현이 이름-값 매핑에 동의한다는 의미에서 상호 운용이 가능합니다. 개체 내에서 이름이 고유하지 않으면 해당 개체를받는 소프트웨어의 동작을 예측할 수 없습니다. 많은 구현에서 성 / 값 쌍만보고합니다. 다른 구현에서는 오류를보고하거나 개체를 구문 분석하지 못하고 일부 구현에서는 중복을 포함하여 모든 이름 / 값 쌍을보고합니다.
다시 말해, RFC 8259의 관점에서 보면 유효하지만 파서는 바프 할 수 있으며 어떤 값이 해당 키와 쌍을 이룰 것인지에 대한 약속이 없습니다. ECMA-404 관점에서 (개인적으로 권한을 갖습니다) 유효 기간입니다. 나에게 이것은 파싱을 거부하는 파서가 손상되었음을 의미합니다. 적어도이 두 표준에 따라 구문 분석해야합니다. 그러나 그것이 선택하는 기본 객체로 바뀌는 방법은 어쨌든 환경과 상황에 완전히 의존하는 고유 키 여부이며, 그중 어느 것도 표준에 없습니다.
ECMA JSON 표준에 정의되어 있지 않습니다 . 그리고 일반적으로 표준의 정의가 부족하다는 것은 "이것이 모든 곳에서 같은 방식으로 작동한다고 생각하지 마십시오"를 의미합니다.
도박꾼 인 경우 "다수"JSON 엔진은 복제를 허용하고 마지막으로 지정된 값을 사용합니다. 이:
var o = {"a": 1, "b": 2, "a": 3}
이것이된다 :
Object {a: 3, b: 2}
그러나 당신이 도박꾼이 아니라면, 그것을 의지하지 마십시오!
표준은 이것을 말합니다 :
프로그래밍 언어는 객체를 지원하는지 여부와 객체가 제공하는 특징 및 제약 조건에 따라 크게 다릅니다. 객체 시스템의 모델은 매우 다양하며 계속 발전하고 있습니다. JSON은 대신 이름 / 값 쌍 모음을 표현하기위한 간단한 표기법을 제공합니다. 대부분의 프로그래밍 언어에는 레코드, 구조체, 받아쓰기, 맵, 해시 또는 객체와 같은 이름으로 갈 수있는 이러한 컬렉션을 나타내는 기능이 있습니다.
버그는 최소한 node.js에 있습니다. 이 코드는 node.js에서 성공합니다.
try {
var json = {"name":"n","name":"v"};
console.log(json); // outputs { name: 'v' }
} catch (e) {
console.log(e);
}
IETF (Internet Engineering Task Force)에서 게시 한 JSON의 현재 표준 인 RFC-7159에 따르면 "객체 내의 이름은 고유해야합니다"라고되어 있습니다. 그러나 IETF 문서에 사용 된 용어를 정의하는 RFC-2119에 따르면 "실제로"라는 단어는 실제로 "..."특정 상황에서 특정 항목을 무시해야하는 유효한 이유가있을 수 있지만 전체 의미를 이해하고 이해해야합니다. 다른 코스를 선택하기 전에 신중하게 무게를 측정했습니다. " 이것이 본질적으로 의미하는 것은 고유 키를 사용하는 것이 권장되지만 필수는 아닙니다. JSON 객체에 중복 키를 가질 수 있으며 여전히 유효합니다.
실제 응용 프로그램에서 JSON에서 중복 키가 발견되면 마지막 키의 값이 고려되는 것을 보았습니다.
C #에서 deserialize Dictionary<string, string>
하면 마지막 키 값 쌍이 필요합니다.
string json = @"{""a"": ""x"", ""a"": ""y""}";
var d = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
// { "a" : "y" }
역 직렬화하려고하면
class Foo
{
[JsonProperty("a")]
public string Bar { get; set; }
[JsonProperty("a")]
public string Baz { get; set; }
}
var f = JsonConvert.DeserializeObject<Foo>(json);
Newtonsoft.Json.JsonSerializationException
예외 가 발생합니다.
Dictionary<string, string>