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

23

Какой формат JSON является лучшим выбором для пар ключ-значение и почему?

[{"key1": "value1"}, {"key2": "value2"}]

Или:

[{"Name": "key1", "Value": "value1"}, {"Name": "key2", "Value": "value2"}]

Или:

{"key1": "value1", "key2": "value2"}

Первый вариант кажется более компактным и более «семантически значимым». Второй вариант выглядит более равномерно структурированным, что может помочь в его обработке. Третий вариант кажется еще более семантическим.

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

boot4life
источник
3
Если вы не требуете заказа, почему бы не рассмотреть {"key1": "value1", "key2": "value2"}?
Kennytm
4
JSON - это уже (нестабильный) словарь.
Кейси Спикман
1
Ваша проблема в том, что описание достаточно широкое, чтобы сказать, что любой из этих форматов будет работать, и реальный вопрос заключается в том, как сделать его проще для потребления, что зависит от того, какие технологии используют клиенты.
scriptin
Вы должны использовать самое простое, которое соответствует вашим потребностям, надеюсь, это будет простая форма объекта (# 3). Однако, если вы ищете еще больше опций, вы можете использовать два массива параллельно, один для ключей и один для значений; это будет как можно более компактно, при этом поддерживая ключи объекта и дубликаты ключей (что не будет поддерживаться с # 3).
Эрик Эйдт

Ответы:

10

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

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

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

Карл Билефельдт
источник
5
Большим преимуществом второго варианта является то, что он работает с нестроковыми ключами, в частности с составными ключами.
CodesInChaos
1
Второй вариант ужасен, и вы еще не нашли вариант использования? Массив словарей со многими парами ключ / значение должен быть наиболее распространенным форматом для передачи нескольких объектов.
gnasher729
2
@ gnasher729, в вашем «самый распространенный формат» случае реальные ключи находятся на стороне левой руки: [{"key1": "value1", "key2": "value2"}]. Второй формат здесь - это размещение реального ключа справа и использование другого ключа «Имя», чтобы указать вам настоящий ключ, что делает его чрезвычайно сложным для анализа стандартными инструментами.
Карл Билефельдт
Я дам тебе это, @CodesInChaos. Даже там, тем не менее, это должен быть особый случай. Я никогда не видел необходимости в этом в дикой природе.
Карл Билефельдт
3
Извините, но это плохой ответ. Второй вариант очень часто используется и рекомендуется. Это обеспечивает гибкость ключей, расширение (с большим количеством полей значений / метаданных), не нарушая потребителей, и может сохранять порядок элементов. Плюс к этому приводятся ложные причины: он не нарушает никакого «автоматического преобразования» (он просто учитывает представление автора в виде массива) и прекрасно работает с интерфейсом запросов, подобным XPath. Единственным недостатком является увеличение многословия.
Hejazzman
5

3-й формат вообще самый лучший. Тем не менее, вот пример чего-то подходящего для первого формата:

[{
  "username": "foo",
  "id": 1
}, {
  "username": "bar",
  "id": 2
}, {
  "username": "baz",
  "id": 3
}]

Здесь каждый объект относится к отдельной вещи (и каждый объект использует те же ключи, что и другие, поэтому они не могут быть объединены). Однако каждый объект в списке хранится { "username": "foo", "id": 1 }не [{ "username": "foo" }, { "id": 1 }]потому, что 1) он короче и 2) он ссылается на одну вещь с именем пользователя и идентификатором, а не на одну вещь с именем пользователя и другую вещь с идентификатором.

Проблема со вторым вариантом заключается в том, что он становится очень многословным как в формате JSON, так и для работы с ним. Однако его можно использовать, если вам нужно хранить метаинформацию об объекте. Пример:

{
  "key": "foo",
  "value": 1,
  "mutable": true
}

Здесь mutableотносится к гипотетическому случаю, если вы можете изменить само свойство, а не родительский объект. Подобная метаинформация похожа на JavaScript Object.defineProperty, которая хранит информацию о свойствах, которую можно конфигурировать, перечислять и записывать.

gcampbell
источник
Я пытался использовать первый формат для некоторого JSON, который я отправлял в конечную точку C # REST, и он не преобразовывался в объект словаря. Преобразование его в 3-й формат прояснилось.
fizch
5

Вы говорите, что это пары ключ / значение. В этом случае используйте # 3: словарь пар ключ / значение.

Если это не пары ключ / значение, не называйте их «ключами» и «значениями» и используйте # 2, массив словарей с произвольным содержимым.

Структура № 1 просто глупа, если вам не нужны пары ключ / значение, но также и их порядок. Что вы редко делаете.

gnasher729
источник
3

Поставьте себя на место человека, получающего JSON. Если я не знаю имя ключа, как я должен получить его с первым или последним форматом? Конечно, вы можете пройтись по json, но поскольку все три формата достигают одного и того же результата, это всего лишь вопрос синтаксиса. Я думаю, что это единственный значимый вопрос: если вы знаете имена ключей, первый или последний вариант более компактны, если нет, то второй вариант более понятен.

JoulinRouge
источник