¿La sintaxis JSON permite claves duplicadas en un objeto?


¿Es este json válido?

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

Http://jsonlint.com/ dice que sí.

Http://www.json.org / no dice nada de que esté prohibido.

Pero obviamente no tiene mucho sentido, ¿verdad? La mayoría de las implementaciones probablemente usan una tabla hash por lo que está siendo anulada de todos modos.

Author: clamp, 2014-02-17

11 answers

De el estándar (p. ii):

Se espera que otros estándares se refieran a este, adhiriéndose estrictamente al formato de texto JSON, mientras que imponer restricciones a varios detalles de codificación. Esas normas pueden requerir comportamientos específicos. JSON no especifica ningún comportamiento.

Más abajo en el estándar (p. 2), la especificación para un objeto JSON:

Una estructura de objeto se representa como un par de llave tokens alrededor de cero o más pares nombre / valor. Un nombre es una cadena. Un único token de dos puntos sigue a cada nombre, separando el nombre del valor. Individual el token de coma separa un valor de un nombre siguiente.

Diagrama para Objeto JSON

No hace ninguna mención de que las claves duplicadas sean inválidas o válidas, por lo que de acuerdo con la especificación asumiría con seguridad que significa que están permitidas.

Que la mayoría de las implementaciones de bibliotecas JSON hacen no aceptar claves duplicadas no entra en conflicto con el estándar, debido a la primera cita.

Aquí hay dos ejemplos relacionados con la biblioteca estándar de C++. Al deserializar algún objeto JSON en un std::map tendría sentido rechazar claves duplicadas. Pero al deserializar algún objeto JSON en un std::multimap tendría sentido aceptar claves duplicadas como normal.

 84
Author: Timothy Shields,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-17 16:10:16

La respuesta corta: Sí, pero no se recomienda.
La respuesta larga: Depende de lo que llames válido...


Las JSON Data Interchange Format (ECMA-404) no dice nada sobre nombres duplicados (claves).

Sin embargo, El formato de Intercambio de Datos de JavaScript Object Notation (JSON) (RFC7159) dice:

Los nombres dentro de un objeto DEBEN ser únicos.

En este contexto debería debe entenderse como se especifica en RFC 2119

SI esta palabra, o el adjetivo "RECOMENDADO", significa que puede existen razones válidas en circunstancias particulares para ignorar un item, pero las implicaciones completas deben ser entendidas y cuidadosamente pesado antes de elegir un curso diferente.



RFC 7159 explica por qué los nombres únicos (claves) son buenos:

Un objeto cuyos nombres son todos únicos es interoperable en el sentido
que todas las implementaciones de software que reciban ese objeto estarán de acuerdo en las asignaciones nombre-valor. Cuando los nombres dentro de un objeto no son
único, el comportamiento del software que recibe tal objeto es
impredecible. Muchas implementaciones reportan el par apellido/valor
solo. Otras implementaciones informan de un error o fallo al analizar el
objeto, y algunas implementaciones reportan todos los pares nombre/valor,
incluyendo duplicados.

JSON se ha observado que las bibliotecas de análisis difieren en cuanto a si o no, hacen que el orden de los miembros del objeto sea visible para llamar software. Implementaciones cuyo comportamiento no depende de member
los pedidos serán interoperables en el sentido de que no serán
afectados por estas diferencias.




Además, como Serguei señaló en los comentarios: ECMA-262 "ECMAScript® Language Specification", dice:

En el caso donde hay cadenas de nombres duplicadas dentro de un objeto, se sobrescribirán los valores que precedan léxicamente a la misma clave.

(en otras palabras, last-value-wins).




Tratando de analizar una cadena con nombres duplicados con la implementación de Java de Douglas Crockford (el creador de JSON) resulta en una excepción:

org.json.JSONException: Duplicate key "status"  at
org.json.JSONObject.putOnce(JSONObject.java:1076)
 90
Author: user454322,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-23 02:37:48

Hay 2 documentos que especifican el formato JSON:

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

La respuesta aceptada cita del 1er documento. Creo que el primer documento es más claro, pero el segundo contiene más detalles.

El segundo documento dice:

  1. Objetos

    Una estructura de objeto se representa como un par de corchetes alrededor de cero o más pares nombre / valor (o miembro). Un nombre es un cadena. Un solo dos puntos viene después de cada nombre, separando el nombre del valor. Una sola coma separa un valor de un siguiente nombre. Los nombres dentro de un objeto DEBEN ser únicos.

Así que no está prohibido tener un nombre duplicado, pero se desaconseja.

 14
Author: toongeorges,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-08 13:07:29

Me encontré con una pregunta similar cuando se trata de una API que acepta XML y JSON, pero no documenta cómo manejaría lo que esperaría que fueran claves duplicadas en el JSON aceptado.

La siguiente es una representación XML válida de su JSON de ejemplo:

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

Cuando esto se convierte en JSON, se obtiene lo siguiente:

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

Una asignación natural de un lenguaje que maneja lo que podría llamar claves duplicadas a otro, puede servir como un potencial mejor referencia práctica aquí.

¡Espero que eso ayude a alguien!

 8
Author: a darren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-19 11:22:40

La especificación JSON dice esto:

Un objeto es un conjunto desordenado de pares nombre/valor.

La parte importante aquí es "desordenada": implica unicidad de claves, porque lo único que puede usar para referirse a un par específico es su clave.

Además, la mayoría de las bibliotecas JSON deserializarán los objetos JSON a mapas/diccionarios hash, donde las claves se garantizan únicas. Lo que sucede cuando se deserializa un objeto JSON con claves duplicadas depende de la biblioteca: en los casos, obtendrá un error o solo se tendrá en cuenta el último valor de cada clave duplicada.

Por ejemplo, en Python, json.loads('{"a": 1, "a": 2}') devuelve {"a": 2}.

 6
Author: Max Noel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-17 15:32:19

Pidiendo un propósito, hay diferentes respuestas:

Usando JSON para serializar objetos (JavaScriptObjectNotation), cada elemento del diccionario se asigna a una propiedad de objeto individual, por lo que las diferentes entradas que definen un valor para la misma propiedad no tienen significado.

Sin embargo, llegué a la misma pregunta de un caso de uso muy específico: Escribiendo muestras JSON para pruebas de API, me preguntaba cómo agregar comentarios a nuestro archivo JSON sin romper la usabilidad. La especificación JSON no lo sabe comentarios, así que se me ocurrió un enfoque muy simple:

Usar claves duplicadas para comentar nuestras muestras JSON. Ejemplo:

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

Los serializadores JSON que estamos usando no tienen problemas con estos duplicados de "OBSERVACIÓN" y nuestro código de aplicación simplemente ignora esta pequeña sobrecarga.

Por lo tanto, a pesar de que no hay significado en la capa de aplicación, estos duplicados para nosotros proporcionan una solución útil para agregar comentarios a nuestras muestras de prueba sin romper el usabilidad del JSON.

 2
Author: aknoepfel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-02 17:13:09

DEBE ser único no significa DEBE ser único. Sin embargo, como se ha dicho, algunos analizadores fallarían y otros solo usarían el último valor analizado. Sin embargo, si la especificación se limpió un poco para permitir duplicados, entonces podría ver un uso donde puede tener un controlador de eventos que está transformando el JSON a HTML o algún otro format...in en tales casos sería perfectamente válido analizar el JSON y crear otro formato de documento...

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

Podría entonces analizar fácilmente a html para ejemplo

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

Puedo ver el razonamiento detrás de la pregunta, pero tal como está...No confiaría en él.

 2
Author: Colin Saxton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-14 17:06:34

No está definido en el estándar ECMA JSON . Y en términos generales, una falta de definición en un estándar significa ,"No cuente con que esto funcione de la misma manera en todas partes."

Si eres un jugador, "muchos" motores JSON permitirán la duplicación y simplemente usarán el último valor especificado. Esto:

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

Se convierte en esto:

Object {a: 3, b: 2}

Pero si no eres un jugador, ¡no cuentes con ello!

 1
Author: svidgen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-17 15:38:36

De acuerdo con RFC-7159, el estándar actual para JSON publicado por Internet Engineering Task Force (IETF), establece que "Los nombres dentro de un objeto DEBEN ser únicos". Sin embargo, de acuerdo con RFC-2119, que define la terminología utilizada en los documentos de IETF, la palabra "should" de hecho significa "... puede haber razones válidas en circunstancias particulares para ignorar un tema en particular, pero todas las implicaciones deben entenderse y sopesarse cuidadosamente antes de elegir un curso diferente."Lo que esto esencialmente significa que si bien se recomienda tener claves únicas, no es una necesidad. Podemos tener claves duplicadas en un objeto JSON, y todavía sería válido.

Desde la aplicación práctica, he visto que el valor de la última clave se considera cuando se encuentran claves duplicadas en un JSON.

 1
Author: Navaneetha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-11 02:47:34

En C# si se deserializa a un Dictionary<string, string> toma el último par de valores de clave:

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

Si intentas deserializar a

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

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

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

Se obtiene una excepción Newtonsoft.Json.JsonSerializationException.

 0
Author: Sam Leach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-17 15:43:43

El estándar dice esto:

Los lenguajes de programación varían ampliamente en cuanto a si soportan objetos, y si es así, qué características y restricciones ofrecen los objetos. El los modelos de sistemas de objetos pueden ser muy divergentes y continúan evolucionar. En su lugar, JSON proporciona una notación simple para expresar colecciones de pares nombre/valor. La mayoría de los lenguajes de programación tendrán alguna característica para representar tales colecciones, que pueden ir por nombres como record, struct, dict, mapa, hash u objeto.

El error está en el nodo.js por lo menos. Este código tiene éxito en el nodo.js.

try {
     var json = {"name":"n","name":"v"};
     console.log(json); // outputs { name: 'v' }
} catch (e) {
     console.log(e);
}
 0
Author: John Carlson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-21 01:39:41