Позволяет ли синтаксис JSON дублировать ключи в объекте?

является ли это допустимым json?

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

http://jsonlint.com/ говорит "Да".

http://www.json.org/ ничего не говорит о том, что это запрещено.

но, очевидно, это не имеет большого смысла, не так ли? Большинство реализаций, вероятно, используют хэш-таблицу, поэтому она в любом случае переопределяется.

11 ответов


С стандарт (стр. ii):

ожидается, что другие стандарты будут ссылаться на этот, строго придерживаясь текстового формата JSON, в то время как наложение ограничений на различные детали кодирования. Такие стандарты могут требовать определенного поведения. формат JSON сама по себе не определяет поведения.

далее вниз в стандарте (стр. 2), спецификация для объекта JSON:

структура объекта представлена как фигурные скобки маркеры окружающих ноль или более пар имя/значение. Имя-это строка. Один маркер двоеточия следует за каждым именем, отделяя имя от значения. Сингл маркер запятой отделяет значение от следующего имени.

Diagram for JSON Object

Он не упоминает о том, что дубликаты ключей недействительны или действительны, поэтому в соответствии со спецификацией я бы с уверенностью предположил, что это означает, что они разрешены.

что большинство реализаций Библиотеки JSON do не accept duplicate keys не конфликтует со стандартом из-за первой цитаты.

вот два примера, связанные со стандартной библиотекой C++. При десериализации некоторого объекта JSON в std::map имеет смысл отказаться от дублирования ключей. Но при десериализации некоторого объекта JSON в std::multimap имело бы смысл принимать дубликаты ключей как обычно.


короткий ответ: Да, но не рекомендуется.
Длинный ответ: Это зависит от того, что вы называете действительным...


The формат обмена данными JSON (ECMA-404) ничего не говорит о дублированных именах (ключах).

однако, формат обмена данными JavaScript Object Notation (JSON)) (RFC7159) говорит:

имена внутри объекта должны быть уникальный.

в этой связи должны необходимо понимать, как указано в RFC 2119

если это слово или прилагательное "рекомендуется" означает, что может существуют веские причины в конкретных обстоятельствах игнорировать определенные пункт, но все последствия должны быть поняты и тщательно взвешивают, прежде чем выбрать другой курс.



RFC 7159 объясняет, почему уникальный имена (ключи) хороши:

объект, имена которого уникальны, взаимодействует в смысле
что все программные реализации, получающие этот объект, согласуются имя-значение сопоставления. Когда имена внутри объекта не
уникальный, поведение программного обеспечения, которое получает такой объект
непредсказуемый. Многие реализации сообщают о паре фамилия/значение
только. Другие реализации сообщают об ошибке или ошибке синтаксического анализа the
объект и некоторые реализации сообщают обо всех парах имя / значение,
включая дубликаты.

парсинг JSON-библиотеки наблюдается отличаются ли или нет, они делают порядок элементов объекта видимым для вызова программное обеспечение. Реализации, поведение которых не зависит от member
заказ полностью совместимых в том смысле, что они не будут
затронуты этими различия.




Также, Как отметил Сергей в комментариях:ECMA-262 " спецификация языка ECMAScript®", гласит:

в случае, когда в объекте есть повторяющиеся строки имен, лексически предшествующие значения для одного и того же ключа должны быть перезаписаны.

(другими словами, последнее значение-wins).




попытка проанализировать a строка с дублированными именами с реализация Java Дугласом Крокфордом (создатель JSON) приводит к исключению:

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

есть 2 документа, определяющие формат JSON:

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

принятый ответ цитирует из 1-го документа. Я думаю, что 1-й документ более ясен, но 2-й содержит больше деталей.

второй документ гласит:

  1. объекты

    структура объекта представлена в виде пары фигурных скобок окружающие ноль или более пар имя/значение (или членов). Имя это строка. Один двоеточие приходит после каждого имени, разделяя имя от значения. Одна запятая отделяет значение от следующего имя. имена внутри объекта должны быть уникальными.

таким образом, не запрещено иметь дубликат имени, но это не рекомендуется.


я столкнулся с аналогичным вопросом при работе с API, который принимает как XML, так и JSON, но не документирует, как он будет обрабатывать то, что вы ожидаете, чтобы быть дубликатами ключей в JSON.

ниже приведено допустимое XML-представление вашего образца JSON:

<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}.


спрашивая о цели, есть разные ответы:

используя JSON для сериализации объектов (JavaScriptObjectNotation), каждый элемент справочника сопоставляется с отдельным свойством объекта, поэтому разные записи, определяющие значение для одного и того же свойства, не имеют значения.

тем не менее, я пришел к тому же вопросу из очень конкретного случая использования: Написание образцов JSON для тестирования API, мне было интересно, как добавить комментарии в наш файл JSON, не нарушая удобство использования. В JSON спецификации не знает комментариев, поэтому придумал очень простой подход:

использовать дубликаты ключей для комментариев наших образцов JSON. Пример:

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

сериализаторы JSON, которые мы используем, не имеют проблем с этими дубликатами" замечаний", и наш код приложения просто игнорирует эти небольшие накладные расходы.

таким образом, даже если нет смысла на уровне приложения, эти дубликаты для нас обеспечивают ценное обходное решение для добавления комментарии к нашим образцам тестирования без нарушения удобства использования JSON.


должно быть уникальным не означает, что должно быть уникальным. Однако, как указано, некоторые Парсеры потерпят неудачу, а другие просто будут использовать последнее проанализированное значение. Однако, если спецификация была немного очищена, чтобы разрешить дубликаты, тогда я мог бы увидеть использование, где у вас может быть обработчик событий, который преобразует 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>

Я вижу обоснование вопроса, но как оно есть...Я бы не поверил.


это не определено в стандарт ECMA JSON. И вообще, отсутствие определения в стандарте означает: "не рассчитывайте на то, что это работает одинаково везде."

Если вы игрок," многие " движки JSON позволят дублировать и просто использовать последнее указанное значение. Это:

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

становится этот:

Object {a: 3, b: 2}

но если вы не игрок,не рассчитывайте на это!


в соответствии с RFC-7159, текущий стандарт для JSON, опубликованный целевой группой по разработке Интернета (IETF), гласит: "имена внутри объекта должны быть уникальными". Однако, согласно RFC-2119, который определяет терминологию, используемую в документах IETF, слово " должно "фактически означает"... в определенных обстоятельствах могут существовать веские причины для игнорирования того или иного пункта, однако, прежде чем выбирать иной путь, необходимо понять и тщательно взвесить все последствия."Что это по сути, это означает, что, хотя рекомендуется иметь уникальные ключи, это не обязательно. Мы можем иметь дубликаты ключей в объекте JSON, и он все равно будет действителен.

из практического применения я видел, что значение из последнего ключа считается, когда дубликаты ключей находятся в JSON.


В C#, если вы deserialise к Dictionary<string, string> Он берет последнюю пару:

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

если вы попытаетесь deserialise к

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 исключения.


стандарт говорит так:

языки программирования сильно различаются в зависимости от того, поддерживают ли они объекты, и если да, то какие характеристики и ограничения предлагают объекты. Этот модели объектных систем могут быть дико расходящимися и продолжают развиваться. Вместо JSON не простая нотация для выражения коллекции пар имя / значение. Большинство языков программирования имеют некоторые функции для представления таких коллекций, которые могут идти по именам как запись, структура, дикт, карта, хэш или объект.

ошибка в узле.Яш, по крайней мере. Этот код успешно выполняется в узле.js.

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