如何用JSON表示集合?


16

JSON支持以下数据结构(等同于Java):标量,数组/列表和映射。

一个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表示集合?

聚苯乙烯

请注意,这个问题仅与JSON有关。我知道可以使用其他格式,例如yaml。仍然...


1
JSON不支持集合,这超出了范围。在应用程序范围内存在一个集合或一个独特的唯一集合。因为它是一个集合,所以使用集合语法会更加明显。
Zymus

1
您为什么要用JSON表示集合?请记住,JSON是一种交换格式。
安德列斯F.

@AndresF。我认为表达值的唯一性是一个好主意。我不会将JSON仅绑定到交换格式。它对于文档存储(例如在MongoDB中)也很有用。
罗恩·克莱因

@RonKlein公平。但是,嗯...不要让我开始使用MongoDB:P
Andres F.

在YAML中,集合表示为您的选项[3],但它具有JSON所没有的特殊表示法。
Jasmijn

Answers:


21

好吧,你不能。如您所说,您可以表示数组和字典。您有两种选择。

将集合表示为数组。优点:从集合到数组再返回的转换通常很容易。缺点:数组具有隐式顺序,而集合没有隐式顺序,因此将相同的集合转换为JSON数组可以创建被视为不同的数组。没有办法强制数组元素是唯一的,因此JSON数组可能不包含有效的集合(显然,您可以忽略重复项;无论如何,这都是有可能发生的)。

将集合表示为字典,每个键具有一个任意值,例如0或null。如果您只是忽略这些值,那将是一个完美的选择。另一方面,您可能没有库支持将字典的键作为集合提取,或将集合转换为字典。

在我的编程环境中,集合和数组之间的转换更容易(设置数组将丢失重复的值,该重复值要么不存在,要么被认为是正确的),因此出于这个原因,我会选择数组。但这很大程度上是一个见解。

但是:屋子里有只大胖大象没有被提及。JSON字典中的键只能是字符串。如果您的集合不是字符串集合,则只能选择使用数组。


5
非字符串的边缘情况是反对字典的一个很好的论据。
罗恩·克莱因

4

不要尝试用JSON表示集合。而是在解析数据时执行此操作。

您的JSON数据应具有一个架构,该架构指定应将哪些字段视为集合,或者您可以在JSON数据本身中嵌入一个元数据,该元数据描述何时应将列表视为集合(例如{"houses": {"_type": "set", "value": [...]}})或使用命名约定。

请注意,根据JSON标准,JSON对象可以具有重复的键。ECMA-404文字:

对象

[...] JSON语法不对用作名称的字符串施加任何限制,不要求名称字符串是唯一的,并且不对名称/值对的排序赋予任何意义。这些都是JSON处理程序可以定义的语义注意事项,也可以在定义JSON用于数据交换的特定用法的规范中定义。

AFAICD,规范中没有任何内容禁止非唯一名称,并且有许多JSON解析器实现可以解析非唯一对象名称。RFC 7159不鼓励使用非唯一的名称来实现互操作性,但具体也不要禁止它,并继续列出如何看到各种解析器处理非唯一的对象名称。

而且ECMA 404也不需要保留数组顺序:

数组

JSON语法未定义值顺序的任何特定含义。但是,JSON数组结构通常用于排序具有某些语义的情况。

此措辞允许应用程序选择使用数组来表示集合。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.