Как представить набор в JSON?

16

JSON поддерживает следующие структуры данных (эквиваленты Java): Scalar, Array / List и Map.

A Setне поддерживается "из коробки" в JSON.

Я подумал о нескольких способах представления набора в JSON:

[1] - в виде списка

Тем не менее, список имеет свой собственный порядок, поэтому следующие два списка ["a", "b"]и ["b", "a"]не равны как списки, но они должны быть равны как наборы.

[2] - как карта

Используйте набор ключей карты и игнорируйте значения.

Но опять же, используя стандартное сравнение, они не совпадают с картами:

{"a": "foo", "b": "bar"}, {"a": null, "b": null}

[3] - как карта с особым значением

Возьмите скаляр, скажем 0или nullи заставьте его быть значением каждого ключа на карте:

{"a": 0, "b": 0}

Таким образом, в стандартных инструментах сравнения объекты равны, даже если порядок клавиш изменен.

Однако этот метод загрязняет документ JSON несущественными данными.

[4] - как упорядоченный список

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

Однако мы должны также учитывать сложность сортировки, а также то, что нотация карты обрабатывает дубликаты, а сортированный список - нет. Пример:

{"a": 400, "a": 9}обрабатывается как {"a": 9}, но ["g", "g"]всегда будет ["g", "g"].

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

Что вы думаете? Как бы вы представили набор в JSON?

PS

Обратите внимание, что вопрос это просто о JSON. Я знаю, что доступны другие форматы, такие как yaml. По-прежнему...

Рон Кляйн
источник
1
Наборы не поддерживаются JSON, это выходит за рамки. Набор, или отдельная, уникальная коллекция, существует в рамках приложения. Поскольку это коллекция, было бы более очевидно использовать синтаксис коллекции.
Зимус
1
Почему вы хотите представлять множества в JSON? Помните, что JSON - это формат обмена.
Андрес Ф.
@AndresF. Я подумал, что было бы неплохо выразить атрибут уникальности значений. Я бы не стал связывать JSON только с форматом обмена. Это также может быть полезно для хранения документов (как в MongoDB).
Рон Кляйн
@RonKlein Достаточно справедливо. Но тьфу ... не
Андрес Ф.
В YAML наборы представлены как ваш вариант [3], но у него есть специальное обозначение, которого нет в JSON.
Jasmijn

Ответы:

21

Ну, ты не можешь. Как вы сказали, вы можете представлять массивы и словари. У вас есть два варианта.

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

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

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

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

gnasher729
источник
5
крайний случай не-строк - хороший аргумент против словаря.
Рон Кляйн
4

Не пытайтесь представлять множества в JSON. Делайте это при анализе данных вместо этого.

Ваши данные JSON должны иметь схему, которая определяет, какие поля должны обрабатываться как набор, или вы можете иметь метаданные, встроенные в сами данные JSON, которые описывают, когда список должен рассматриваться как набор (например {"houses": {"_type": "set", "value": [...]}}) или с соглашением об именах.

Обратите внимание, что согласно стандарту JSON объект JSON может иметь дубликаты ключей. Формулировки ECMA-404:

Объекты

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

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

И ECMA 404 также не требует сохранения порядка массива:

Массивы

Синтаксис JSON не определяет какого-либо конкретного значения для упорядочения значений. Тем не менее, структура массива JSON часто используется в ситуациях, когда есть некоторая семантика для упорядочения.

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

Ли Райан
источник