La syntax JSON consente chiavi duplicate in un object?

È questo json valido?

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

http://jsonlint.com/ dice di si.

http://www.json.org/ non dice nulla che sia proibito.

Ma ovviamente non ha molto senso, vero? La maggior parte delle implementazioni utilizza probabilmente un hashtable, quindi viene comunque sovrascritto.

Dallo standard (pagina ii) :

Si prevede che altri standard faranno riferimento a questo, rispettando rigorosamente il formato di testo JSON, imponendo restrizioni sui vari dettagli di codifica. Tali standard possono richiedere comportamenti specifici. Lo stesso JSON non specifica alcun comportamento.

Più in basso nello standard (p.2), le specifiche per un object JSON:

Una struttura di object è rappresentata come una coppia di token parentesi graffe che circondano zero o più coppie nome / valore. Un nome è una stringa. Un singolo token del colon segue ciascun nome, separando il nome dal valore. Un singolo token a virgola separa un valore da un nome seguente.

Diagramma per oggetto JSON

Non fa alcuna menzione che le chiavi duplicate siano non valide o valide, quindi in base alle specifiche presumo che ciò sia consentito.

La maggior parte delle implementazioni delle librerie JSON non accetta chiavi duplicate non in conflitto con lo standard, a causa della prima citazione.

Ecco due esempi relativi alla libreria standard C ++. Quando deserializza qualche object JSON in una std::map , avrebbe senso rifiutare chiavi duplicate. Ma quando deserializza qualche object JSON in una std::multimap , avrebbe senso accettare chiavi duplicate come di consueto.

La risposta breve: Sì ma non è raccomandato.
La lunga risposta: dipende da ciò che chiami valido …

Il JSON Data Interchange Format (ECMA-404) non dice nulla sui nomi duplicati (chiavi).

Tuttavia, il formato di interscambio dati JSON (JavaScript Object Notation) (RFC7159) dice:

I nomi all’interno di un object DOVREBBE essere unici.

In questo contesto dovrebbe essere compreso come specificato nella RFC 2119

DOVREBBE Questa parola, o l’aggettivo “RACCOMANDATO”, significa che possono esistere ragioni valide in circostanze particolari per ignorare un particolare elemento, ma le implicazioni complete devono essere comprese e attentamente ponderate prima di scegliere un corso diverso.

RFC 7159 spiega perché i nomi univoci (chiavi) sono buoni:

Un object i cui nomi sono tutti unici è interoperabile nel senso
che tutte le implementazioni software che ricevono quell’object concorderanno sui mapping del nome-valore. Quando i nomi all’interno di un object non lo sono
unico, il comportamento del software che riceve tale object è
imprevedibile. Molte implementazioni riportano il cognome / coppia di valori
solo. Altre implementazioni riportano un errore o non riescono a analizzare il
object e alcune implementazioni riportano tutte le coppie nome / valore,
compresi i duplicati.

È stato osservato che le librerie di analisi JSON differiscono sul fatto se rendono l’ordine dei membri degli oggetti visibile o meno al software di chiamata. Implementazioni il cui comportamento non dipende dal membro
l’ordine sarà interoperabile nel senso che non lo sarà
influenzato da queste differenze.


Inoltre, come sottolineato da Serguei nei commenti: ECMA-262 “Specifica linguaggio ECMAScript®”, si legge:

Nel caso in cui vi siano stringhe di nome duplicate all’interno di un object, i valori precedenti lessicali per la stessa chiave devono essere sovrascritti.

(in altre parole, vince l’ultimo valore).


Cercando di analizzare una stringa con nomi duplicati con l’ implementazione Java di Douglas Crockford (il creatore di JSON) si ottiene un’eccezione:

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

Ci sono 2 documenti che specificano il formato JSON:

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

La risposta accettata cita dal primo documento. Penso che il primo documento sia più chiaro, ma il secondo contiene maggiori dettagli.

Il secondo documento dice:

  1. Oggetti

    Una struttura di object è rappresentata come una coppia di parentesi graffe che circondano zero o più coppie nome / valore (o membri). Un nome è una stringa. Un singolo due punti viene dopo ogni nome, separando il nome dal valore. Una singola virgola separa un valore da un nome seguente. I nomi all’interno di un object DOVREBBE essere unici.

Quindi non è vietato avere un nome duplicato, ma è scoraggiato.

Mi sono imbattuto in una domanda simile quando ho a che fare con un’API che accetta sia XML che JSON, ma non documenta come gestirà ciò che ci si aspetterebbe essere chiavi duplicate nel JSON accettato.

Quanto segue è una rappresentazione XML valida del tuo JSON di esempio:

  x y  

Quando questo viene convertito in JSON, ottieni quanto segue:

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

Una mapping naturale da un linguaggio che gestisce ciò che potreste chiamare chiavi duplicate a un altro, può servire come riferimento potenziale per le migliori pratiche qui.

Spero che aiuti qualcuno!

La specifica JSON dice questo:

Un object è un insieme non ordinato di coppie nome / valore.

La parte importante qui è “non ordinata”: implica l’univocità delle chiavi, perché l’unica cosa che puoi usare per riferirsi a una coppia specifica è la sua chiave.

Inoltre, la maggior parte delle librerie JSON deserializza oggetti JSON in hash maps / dizionari, dove le chiavi sono univoche garantite. Ciò che accade quando deserializzi un object JSON con chiavi duplicate dipende dalla libreria: nella maggior parte dei casi, riceverai un errore, o verrà preso in considerazione solo l’ultimo valore per ogni chiave duplicata.

Ad esempio, in Python, json.loads('{"a": 1, "a": 2}') restituisce {"a": 2} .

Chiedendo lo scopo, ci sono diverse risposte:

Usando JSON per serializzare oggetti (JavaScriptObjectNotation), ogni elemento del dizionario si associa a una proprietà di object indivuale, quindi le diverse voci che definiscono un valore per la stessa proprietà non hanno significato.

Tuttavia, ho trovato la stessa domanda da un caso d’uso molto specifico: scrivendo campioni JSON per test API, mi chiedevo come aggiungere commenti nel nostro file JSON senza rompere l’usabilità. Le specifiche JSON non conoscono i commenti, quindi ho trovato un approccio molto semplice:

Per utilizzare chiavi duplicate per commentare i nostri campioni JSON . Esempio:

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

I serializzatori JSON che stiamo usando non hanno problemi con questi duplicati “REMARK” e il nostro codice applicativo semplicemente ignora questo piccolo overhead.

Pertanto, anche se non vi è alcun significato sul livello dell’applicazione, questi duplicati rappresentano una valida soluzione per aggiungere commenti ai nostri campioni di test senza compromettere l’usabilità del JSON.

DOVREBBE essere unico non vuol dire DEVE essere unico. Comunque, come detto, alcuni parser fallirebbero e altri avrebbero semplicemente usato l’ultimo valore analizzato. Tuttavia, se la specifica è stata ripulita un po ‘per consentire i duplicati, potrei vedere un uso in cui potresti avere un gestore di eventi che sta trasformando il JSON in HTML o qualche altro formato … in questi casi sarebbe perfettamente valido per analizzare il JSON e creare un altro formato di documento …

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

potrebbe quindi facilmente analizzare in HTML, ad esempio

  

hello

universe

Heading 1

another paragraph

Riesco a vedere il ragionamento alla base della domanda, ma così com’è … non mi fiderei di esso.

Non è definito nello standard ECM JSON . E in generale, una mancanza di definizione in uno standard significa “Non contare su questo lavorare allo stesso modo ovunque”.

Se sei un giocatore d’azzardo, “molti” motori JSON permetteranno la duplicazione e useranno semplicemente il valore dell’ultimo specifico. Questo:

 var o = {"a": 1, "b": 2, "a": 3} 

Diventa questo:

 Object {a: 3, b: 2} 

Ma se non sei un giocatore d’azzardo, non contarci!

Secondo RFC-7159, lo standard corrente per JSON pubblicato da Internet Engineering Task Force (IETF), afferma “I nomi all’interno di un object DOVREBBE essere unici”. Tuttavia, secondo la RFC-2119 che definisce la terminologia utilizzata nei documenti IETF, la parola “dovrebbe” in realtà significa “… possono esistere ragioni valide in circostanze particolari per ignorare un particolare elemento, ma le implicazioni complete devono essere comprese e attentamente pesato prima di scegliere un corso diverso. ” Ciò che questo significa in sostanza è che pur avendo le chiavi univoche è raccomandato, non è un dovere. Possiamo avere chiavi duplicate in un object JSON e sarebbe comunque valido.

Dall’applicazione pratica, ho visto il valore dell’ultima chiave è considerato quando si trovano chiavi duplicate in un JSON.

In C # se si deserializza in un Dictionary prende l’ultima coppia di valori chiave:

 string json = @"{""a"": ""x"", ""a"": ""y""}"; var d = JsonConvert.DeserializeObject>(json); // { "a" : "y" } 

se provi a deserializzare

 class Foo { [JsonProperty("a")] public string Bar { get; set; } [JsonProperty("a")] public string Baz { get; set; } } var f = JsonConvert.DeserializeObject(json); 

ottieni un’eccezione Newtonsoft.Json.JsonSerializationException .

Lo standard dice questo:

I linguaggi di programmazione variano notevolmente a seconda che supportino gli oggetti e, in tal caso, quali caratteristiche e vincoli gli oggetti offrono. I modelli di sistemi object possono essere selvaggiamente divergenti e continuano a evolversi. JSON fornisce invece una semplice notazione per esprimere collezioni di coppie nome / valore. La maggior parte dei linguaggi di programmazione avrà alcune funzionalità per rappresentare tali raccolte, che possono andare per nome come record, struct, dict, map, hash o object.

Il bug è almeno in node.js. Questo codice ha successo in node.js.

 try { var json = {"name":"n","name":"v"}; console.log(json); // outputs { name: 'v' } } catch (e) { console.log(e); }