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

Действительно ли это json?

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

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

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

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

Ответ 1

Из стандарта (стр. ii):

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

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

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

Diagram for JSON Object

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

То, что большинство реализаций библиотек JSON не принимают дубликаты ключей, не противоречит стандарту из-за первой цитаты.

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

Ответ 2

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


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

Тем не менее, формат обмена данными JavaScript (NSON) (RFC7159) гласит:

Имена внутри объекта ДОЛЖНЫ быть уникальными.

В этом контексте следует понимать, как указано в RFC 2119

СЛЕДУЕТ Это слово или прилагательное "РЕКОМЕНДУЕМЫЕ" означают, что могут существовать веские причины в определенных обстоятельствах игнорировать конкретный элемент, но все последствия должны быть поняты и тщательно взвешены, прежде чем выбрать другой курс.



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

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

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




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

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

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




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

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

Ответ 3

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

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

В 2-м документе говорится:

  1. Объекты

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

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

Ответ 4

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

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

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

Когда это преобразуется в JSON, вы получаете следующее:

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

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

Надеюсь, что это поможет кому-то!

Ответ 5

Спецификация JSON говорит об этом:

Объект представляет собой неупорядоченный набор пар имя/значение.

Важная часть здесь "неупорядоченная": она подразумевает уникальность клавиш, потому что единственное, что вы можете использовать для ссылки на определенную пару, - это ее ключ.

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

Например, в Python json.loads('{"a": 1, "a": 2}') возвращает {"a": 2}.

Ответ 6

Задавая цель, есть разные ответы:

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

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

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

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

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

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

Ответ 7

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

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

Ответ 8

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

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

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

Становится следующим:

Object {a: 3, b: 2}

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

Ответ 9

Согласно RFC-7159, действующий стандарт JSON, опубликованный Целевой группой Internet Engineering Task Force (IETF), гласит: "Имена внутри объекта ДОЛЖНЫ быть уникальными". Однако, согласно RFC-2119, который определяет терминологию, используемую в документах IETF, слово "должно" на самом деле означает "... в определенных обстоятельствах могут существовать обоснованные причины, чтобы игнорировать конкретный элемент, но следует понимать все последствия и тщательно взвешивались, прежде чем выбирать другой курс". Это, по сути, означает, что, хотя рекомендуется использовать уникальные ключи, это не обязательно. Мы можем иметь дубликаты ключей в объекте JSON, и он все равно будет действительным.

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

Ответ 10

В С#, если вы десериализуете , он берет последнюю пару значений ключа:

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.

Ответ 11

В стандарте говорится следующее:

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

Исправлена ​​ошибка в node.js. Этот код преуспевает в node.js.

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

Ответ 12

Отправка и ответ, потому что есть много устаревших идей и путаницы в отношении стандартов. По состоянию на декабрь 2017 года существует два конкурирующих стандарта:

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) как,

  1. СЛЕДУЕТ Это слово или прилагательное "РЕКОМЕНДУЕМЫЕ" означают, что могут существовать веские причины в определенных обстоятельствах игнорировать конкретный элемент, но все последствия должны быть поняты и тщательно взвешены, прежде чем выбрать другой курс.

ECMA-404:

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

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

Причина, по которой дана уникальная ключевая рекомендация в RFC 8259, заключается в следующем:

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

Другими словами, с точки зрения RFC 8259, он действителен, но ваш анализатор может прервать его, и нет никаких обещаний относительно того, какое значение, если оно есть, будет связано с этим ключом. С точки зрения ECMA-404 (которую я лично принял бы за авторитет), это действительно, точка. Для меня это означает, что любой синтаксический анализатор, который отказывается анализировать его, сломан. Следует хотя бы разобрать согласно обоим этим стандартам. Но то, как он превращается в ваш родной объект выбора, в любом случае, является уникальным ключом или нет, полностью зависит от среды и ситуации, и с самого начала ничего из этого не входит в стандарт.