web-dev-qa-db-fra.com

La syntaxe JSON autorise-t-elle les clés en double dans un objet?

Est-ce valide json?

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

http://jsonlint.com/ dit oui.

http://www.json.org/ ne dit rien de l'interdiction.

Mais évidemment, cela n’a pas beaucoup de sens, n'est-ce pas? La plupart des implémentations utilisent probablement une table de hachage, elle est donc annulée de toute façon.

145
clamp

De la norme (p. Ii) :

On s'attend à ce que d'autres normes fassent référence à celle-ci, en respectant strictement le format de texte JSON, tandis que imposer des restrictions sur divers détails de codage. De telles normes peuvent nécessiter des comportements spécifiques. JSON lui-même ne spécifie aucun comportement. 

Plus bas dans la norme (p. 2), la spécification d'un objet JSON:

Une structure d'objet est représentée par une paire de jetons d'accolade entourant zéro ou plusieurs paires nom/valeur. Un nom est une chaîne. Un seul jeton de deux points suit chaque nom, en le séparant de la valeur. Un célibataire ou Individual Le jeton de virgule sépare une valeur d'un nom suivant. 

Diagram for JSON Object

Il ne fait aucune mention des clés en double non valides ou valides, donc, selon la spécification, je supposerais sans risque que cela signifie qu'elles sont autorisées.

Le fait que la plupart des implémentations de bibliothèques JSON acceptent pas accepter les clés en double n'entre pas en conflit avec la norme, à cause du premier guillemet.

Voici deux exemples liés à la bibliothèque standard C++. Lors de la désérialisation d'un objet JSON dans un std::map, il serait logique de refuser les clés en double. Toutefois, lors de la désérialisation d'un objet JSON dans un std::multimap, il serait logique d'accepter les clés en double comme d'habitude.

90
Timothy Shields

La réponse courte: oui mais n'est pas recommandé .
La réponse longue: Cela dépend de ce que vous appelez valide ...


Le format d'échange de données JSON (ECMA-404) ne dit rien des noms dupliqués (clés).

Cependant, format d'échange de données JSON (Notation d'objet JavaScript))} (RFC7159) dit:

Les noms contenus dans un objet DEVRAIENT être uniques.

Dans ce contexte, devrait doit être compris comme spécifié dans RFC 2119

DEVRAIT-il que ce mot, ou l’adjectif "RECOMMANDÉ", signifie qu’il peut existe des raisons valables dans des circonstances particulières pour ignorer un .__ particulier. point, mais toutes les implications doivent être comprises et soigneusement pesé avant de choisir un cours différent.



La RFC 7159 explique pourquoi les noms uniques (clés) sont bons:

Un objet dont les noms sont tous uniques est interopérable au sens
que toutes les implémentations logicielles recevant cet objet s’accorderont sur les mappages nom-valeur. Quand les noms dans un objet ne sont pas
unique, le comportement du logiciel qui reçoit un tel objet est
imprévisible. De nombreuses implémentations signalent la paire nom/valeur
seulement. D'autres implémentations signalent une erreur ou ne parviennent pas à analyser le
objet, et certaines implémentations rapportent toutes les paires nom/valeur,
y compris les doublons.

On a observé que les bibliothèques d'analyse JSON différaient quant à savoir si ou non, ils rendent visible la commande des membres de l'objet à l'appel Logiciel. Implémentations dont le comportement ne dépend pas du membre
la commande sera interopérable dans le sens où ils ne seront pas
affectés par ces différences.




En outre, comme l'a souligné Serguei dans les commentaires: ECMA-262 "ECMAScript® Language Specification", se lit comme suit:

Dans le cas où il existe des noms en double Chaînes dans un objet, les valeurs précédant lexicalement pour la même clé doivent être écrasées.

(en d'autres termes, la dernière valeur gagne).




Essayer d’analyser une chaîne avec des noms dupliqués avec l’implémentation Java de par Douglas Crockford (le créateur de JSON) entraîne une exception:

org.json.JSONException: Duplicate key "status"  at
org.json.JSONObject.putOnce(JSONObject.Java:1076)
98
user454322

Il y a 2 documents spécifiant le format JSON:

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

La réponse acceptée cite le premier document. Je pense que le premier document est plus clair, mais le deuxième contient plus de détails.

Le 2ème document dit:

  1. Objets

    Une structure d'objet est représentée par une paire d'accolades entourant zéro ou plusieurs paires nom/valeur (ou membres). Un nom est un chaîne. Un seul deux-points vient après chaque nom, en le séparant de la valeur. Une seule virgule sépare une valeur de la suivante prénom. Les noms contenus dans un objet DEVRAIENT être uniques.

Il n’est donc pas interdit d’avoir un nom en double, mais cela est déconseillé.

18
toongeorges

Je suis tombé sur une question similaire en ce qui concerne une API qui accepte à la fois XML et JSON, mais ne documente pas la façon dont elle gérera ce que vous vous attendez à être des clés dupliquées dans le JSON accepté.

Voici une représentation XML valide de votre exemple de code JSON:

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

Lorsque cela est converti en JSON, vous obtenez le texte suivant:

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

Un mappage naturel à partir d'une langue qui gère ce que vous pourriez appeler des clés en double peut également servir de référence potentielle de meilleure pratique ici. 

J'espère que ça aide quelqu'un!

8
a darren

La spécification JSON dit ceci:

Un objet est un ensemble non ordonné de paires nom/valeur.

La partie importante ici est "non ordonnée": cela implique l'unicité des clés, car la seule chose que vous pouvez utiliser pour faire référence à une paire spécifique est sa clé.

En outre, la plupart des bibliothèques JSON désérialisent les objets JSON en cartes de hachage/dictionnaires, les clés étant garanties uniques. Ce qui se passe lorsque vous désérialisez un objet JSON avec des clés dupliquées dépend de la bibliothèque: dans la plupart des cas, vous obtiendrez une erreur ou seule la dernière valeur de chaque clé dupliquée sera prise en compte.

Par exemple, en Python, json.loads('{"a": 1, "a": 2}') renvoie {"a": 2}.

6
Max Noel

DEVRAIT être unique ne veut pas dire DOIT être unique. Cependant, comme indiqué, certains analyseurs échouent et d'autres n'utilisent que la dernière valeur analysée. Cependant, si la spécification était un peu nettoyée pour permettre les doublons, je pourrais voir une utilisation dans laquelle vous pourriez avoir un gestionnaire d'événements transformant le JSON en HTML ou en un autre format ... Dans ce cas, il serait parfaitement valide de analyser le JSON et créer un autre format de document ...

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

pourrait alors facilement analyser en HTML par exemple

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

Je peux voir le raisonnement derrière la question, mais dans l’état actuel, je n’aurais pas confiance en elle.

3
Colin Saxton

En cherchant un but, il y a différentes réponses:

En utilisant JSON pour sérialiser des objets (JavaScriptObjectNotation), chaque élément du dictionnaire est mappé sur une propriété d'objet individuelle. Par conséquent, différentes entrées définissant une valeur pour la même propriété n'ont aucune signification.

Cependant, je suis venu à la même question à partir d'un cas d'utilisation très spécifique: En écrivant des exemples JSON pour les tests d'API, je me demandais comment ajouter des commentaires dans notre fichier JSON sans compromettre la convivialité. La spécification JSON ne connaissant pas les commentaires, j'ai donc proposé une approche très simple:

Utiliser des clés dupliquées pour commenter nos exemples JSON . Exemple:

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

Les sérialiseurs JSON que nous utilisons n'ont aucun problème avec ces doublons "REMARK" et notre code d'application ignore tout simplement cette légère surcharge.

Ainsi, même si cela n'a aucun sens sur la couche application, ces doublons constituent pour nous une solution de contournement utile pour ajouter des commentaires à nos échantillons de test sans compromettre la convivialité du JSON.

2
aknoepfel

Selon la norme RFC-7159, la norme actuelle pour le format JSON publiée par l'IETF (Internet Engineering Task Force) stipule que "les noms contenus dans un objet DEVRAIENT être uniques". Cependant, conformément à la RFC-2119 qui définit la terminologie utilisée dans les documents IETF, le mot "devrait" signifie en fait "... il peut exister des raisons valables dans des circonstances particulières pour ignorer un élément particulier, mais il faut comprendre toutes soigneusement pesé avant de choisir un autre cours. " Cela signifie essentiellement que bien qu'il soit recommandé d'avoir des clés uniques, ce n'est pas une obligation. Nous pouvons avoir des clés en double dans un objet JSON et celui-ci serait toujours valide.

De l'application pratique, j'ai vu la valeur de la dernière clé est considérée lorsque des clés en double sont trouvées dans un JSON.

1
Navaneetha

Ce n'est pas défini dans la norme ECMA JSON standard . Et d’une manière générale, l’absence de définition dans une norme signifie: "Ne comptez pas sur cette méthode pour fonctionner de la même manière partout."

Si vous êtes un joueur, "de nombreux" moteurs JSON permettront la duplication et utiliseront simplement la dernière valeur spécifiée. Ce:

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

Devient ceci:

Object {a: 3, b: 2}

Mais si vous n'êtes pas joueur, ne comptez pas dessus!

1
svidgen

Publiez et répondez parce qu'il y a beaucoup d'idées dépassées et de confusion au sujet des normes. À compter de décembre 2017, il existe deux normes en concurrence:

RFC 8259 - https://tools.ietf.org/html/rfc8259

ECMA-404 - http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf

json.org suggère qu'ECMA-404 est le le standard, mais ce site ne semble pas être une autorité. Bien que je pense qu'il soit juste de considérer l'ECMA comme une autorité, ce qui est important ici, c'est que la RFC 8259 stipule que les clés devraient être uniques, et l'ECMA-404 indique qu'elles sont uniques. pas nécessaire que soit unique.

RFC-8259: 

"Les noms contenus dans un objet DEVRAIENT être uniques."

Le mot "devrait" dans toutes les majuscules comme cela, a une signification dans le monde RFC, qui est spécifiquement définie dans une autre norme (BCP 14, RFC 2119 - https://tools.ietf.org/html/rfc2119 ) comme

  1. Ce mot, ou l'adjectif "recommandé", signifie-t-il que il peut exister des raisons valables dans des circonstances particulières pour ignorer un élément particulier, mais toutes les implications doivent être comprises et soigneusement pesé avant de choisir un cours différent.

ECMA-404: 

"La syntaxe JSON n'impose aucune restriction aux chaînes utilisées En tant que noms, ne nécessite pas que les chaînes de noms soient uniques et n'attribue aucune signification à l'ordre des paires nom/valeur."

Donc, peu importe comment vous le découpez, c'est JSON syntaxiquement valide.

La raison donnée pour la recommandation de clé unique dans le RFC 8259 est, 

Un objet dont les noms sont tous uniques est interopérable au sens que toutes les implémentations logicielles recevant cet objet s’accorderont sur les mappages nom-valeur. Lorsque les noms dans un objet ne sont pas unique, le comportement du logiciel qui reçoit un tel objet est imprévisible. De nombreuses implémentations signalent la paire nom/valeur seulement. D'autres implémentations signalent une erreur ou ne parviennent pas à analyser le fichier objet, et certaines implémentations rapportent toutes les paires nom/valeur, y compris les doublons.

En d'autres termes, du point de vue de la RFC 8259, il est valide, mais votre analyseur syntaxique peut déceler et il n'y a aucune promesse quant à la valeur, le cas échéant, qui sera associée à cette clé. Du point de vue de l'ECMA-404 (que je prendrais personnellement pour autorité), c'est valide, point à la ligne. Pour moi, cela signifie que tout analyseur qui refuse de l'analyser est cassé. Il faut au moins analyser selon ces deux normes. Mais la manière dont il est transformé en votre objet de choix natif est, dans tous les cas, des clés uniques ou non, totalement dépendante de l'environnement et de la situation, et rien de tout cela n'est dans la norme pour commencer.

0
xthr33

En C #, si vous désérialisez en un Dictionary<string, string>, il prend la dernière paire de valeurs de clé:

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

si vous essayez de désérialiser à 

class Foo
{
    [JsonProperty("a")]
    public string Bar { get; set; }

    [JsonProperty("a")]
    public string Baz { get; set; }
}

var f = JsonConvert.DeserializeObject<Foo>(json);

vous obtenez une exception Newtonsoft.Json.JsonSerializationException.

0
Sam Leach

La norme dit ceci:

Les langages de programmation varient considérablement selon qu'ils supportent les objets et si tel est le cas, quelles sont les caractéristiques et les contraintes offertes par les objets. Le les modèles de systèmes d'objets peuvent être très divergents et continuent à évoluer. JSON fournit plutôt une simple notation pour exprimer collections de paires nom/valeur. La plupart des langages de programmation auront certaines fonctionnalités pour représenter ces collections, qui peuvent aller par noms comme record, struct, dict, map, hash ou object.

Le bogue est dans node.js au moins. Ce code réussit dans node.js.

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