これは有効なjsonですか?
{
"a" : "x",
"a" : "y"
}
http://jsonlint.com/は「はい」と言っています。
http://www.json.org/は、禁止されていることについては何も述べていません。
しかし、明らかにそれはあまり意味がありませんね。ほとんどの実装ではおそらくハッシュテーブルを使用するため、とにかくオーバーライドされます。
これは有効なjsonですか?
{
"a" : "x",
"a" : "y"
}
http://jsonlint.com/は「はい」と言っています。
http://www.json.org/は、禁止されていることについては何も述べていません。
しかし、明らかにそれはあまり意味がありませんね。ほとんどの実装ではおそらくハッシュテーブルを使用するため、とにかくオーバーライドされます。
回答:
さまざまなエンコーディングの詳細に制限を課しながら、JSONテキスト形式に厳密に従って、他の標準がこれを参照すると予想されます。このような規格では、特定の動作が必要になる場合があります。JSON自体は動作を指定していません。
標準(p。2)のさらに下に、JSONオブジェクトの仕様を示します。
オブジェクト構造は、0個以上の名前と値のペアを囲む中括弧トークンのペアとして表されます。名前は文字列です。各名前の後に単一のコロントークンが続き、名前と値が区切られます。1つのコンマトークンで、値と後続の名前を区切ります。
重複するキーが無効または有効であることについては触れていません。そのため、仕様によると、私はそれらが許可されていることを意味すると安全に想定しています。
JSONライブラリのほとんどの実装では、ので、最初の引用符の、標準としないの競合重複したキーを受け入れます。
次に、C ++標準ライブラリに関連する2つの例を示します。一部のJSONオブジェクトをに逆シリアル化するstd::map
場合、重複するキーを拒否することは理にかなっています。ただし、JSONオブジェクトをに逆シリアル化するstd::multimap
場合、通常どおり重複キーを受け入れることは理にかなっています。
std::multimap
今追加した例を考えてみましょう。キーが重複する可能性のあるJSONオブジェクトとしてシリアル化できます。
{"a":1,"a":2}
2つの異なるキーと値のペアのセットです。実際、{"a":1,"a":1}
たった1つの要素しか持たないキー/値ペアのセットと考えることもできます。それが繰り返されるという事実は、単なる構文上の癖と考えることができます。より適切な定義は、「オブジェクトは文字列(名前)から値への部分的な関数です」です。
短い答え:はい、しかしお勧めできません。
長い答え:それはあなたが有効と呼ぶものに依存します...
ECMA-404「JSONデータ交換構文」は、重複した名前(キー)について何も述べていません。
ただし、RFC 8259「JavaScript Object Notation(JSON)Data Interchange Format」には次のように記載されています。
オブジェクト内の名前は一意である必要があります。
この文脈においてSHOULDで指定されるように理解されなければならないBCP 14:
すべきである。この単語、あるいは形容詞「推奨」は、そこに特定の項目を無視する特定の事情の正当な理由が存在するかもしれないが、完全な意味合いが異なるコースを選択する前に理解し、慎重に検討しなければならないということを意味します。
RFC 8259は、一意の名前(キー)が優れている理由を説明しています。
名前がすべて一意のオブジェクトは、そのオブジェクトを受け取るすべてのソフトウェア実装が名前と値のマッピングに同意するという意味で相互運用可能です。オブジェクト内の名前が一意でない場合、そのようなオブジェクトを受け取るソフトウェアの動作は予測できません。多くの実装は、姓/値のペアのみを報告します。他の実装はエラーを報告するか、オブジェクトの解析に失敗し、一部の実装は重複を含むすべての名前/値ペアを報告します。
また、セルゲイがコメントで指摘したように、ECMA-262「ECMAScript®言語仕様」は次のように述べています。
オブジェクト内に名前の文字列が重複している場合、同じキーの字句的に先行する値は上書きされます。
言い換えれば、最後の価値が勝ちます。
JSONの作成者であるDouglas Crockfordによる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形式を指定する2つのドキュメントがあります。
受け入れられた回答は最初の文書から引用します。1番目のドキュメントの方がわかりやすいと思いますが、2番目のドキュメントの方が詳細です。
2番目のドキュメントは言う:
オブジェクト
オブジェクト構造は、0個以上の名前と値のペア(またはメンバー)を囲む中括弧のペアとして表されます。名前は文字列です。各名前の後にコロンを1つ付けて、名前と値を区切ります。1つのカンマで値と後続の名前を区切ります。 オブジェクト内の名前は一意である必要があります。
したがって、重複した名前を持つことは禁止されていませんが、お勧めしません。
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(実際の標準)が単語「セット」を使用して回避: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月現在、2つの標準が競合しています。
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)で具体的に定義されています。
- この単語または「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);
}
RFC-7159によると、インターネット技術標準化委員会(IETF)によって発行されたJSONの現在の標準では、「オブジェクト内の名前は一意である必要があります」と記載されています。ただし、IETF文書で使用される用語を定義しているRFC-2119によると、「すべき」という言葉は実際には「...別のコースを選択する前に慎重に検討しました。」これが本質的に意味することは、一意のキーを持つことをお勧めしますが、必須ではないということです。JSONオブジェクトに重複したキーを含めることができますが、それはまだ有効です。
実際のアプリケーションでは、JSONで重複するキーが見つかったときに最後のキーの値が考慮されることを確認しました。
C#では、逆シリアル化する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>