对象数组 vs 对象对象

69

这个问题是决定以下符号表示法之间的权衡:

基于 JSON 的

"users": {
    "id1": {
        "id": "id1",
        "firstname": "firstname1",
        "lastname": "lastname1"
    },
    "id2": {
        "id": "id2",
        "firstaame": "firstname2",
        "lastname": "lastname2"
    }
}

基于数组:

users: [
    {
        "id": "id",
        "key2": "value2",
        "key3": "value3"
    },
    {
        "id": "id",
        "key2": "value2",
        "key3": "value3"
    }
]

关于此帖的同一问题,我已经决定(在前端)使用JSON对象表示法而不是对象数组,因为它符合我的要求,提供更好的性能,并且在浏览器中生成较少的代码。

但问题在于列表本身并不是静态的。我的意思是,列表是通过Java API从数据库(NoSQL)获取/存储并为新条目创建的。我无法决定应该在后端使用哪种表示法(最终也会影响用户界面)。

欢迎对性能、可维护性或可扩展性提出任何想法/建议。


2
你是如何比较这两种方法的?在基于JSON的方法中,你将值放置为ID,在基于数组的方法中,你将其放置为数组。你的要求是什么? - Naman Gala
1
在Javascript中,我可以使用id(对于JSON)获取对象,但是在数组的情况下,我必须遍历整个列表并匹配每个对象的id属性,这可能会成为大数据集情况下的瓶颈。因此,JSON在浏览器中很好用,但我不确定Java创建相同结构是否会有任何性能问题。 - me_digvijay
1
你的JSON方法如何支持多个用户输入? - Naman Gala
1
@NamanGala:请查看更新后的JSON示例。 - me_digvijay
2
请注意,JSON始终具有一个根元素,该元素可以是对象{}或数组[]。因此,“基于Json”的术语与“基于数组”的术语实际上应该是“(Json)-基于对象”与“(Json)-基于数组”。 - maja
显示剩余2条评论
6个回答

24

这是一个完全主观的问题。可能会有许多其他要点,但我在下面列出了一些:

基于 JSON 的方法: 如果我没错的话,那么服务器端将使用 Map 实现。

优点:在 JavaScript 中,您可以直接使用 users.id1users.id2,即无需迭代。

缺点:在客户端上,您需要在 JSON 中存在 id,即硬编码它们或使用一些动态方法告诉您 JSON 中存在哪个 id。


基于数组的方法:如果我没错的话,那么服务器端将使用 Array/List 实现。

优点:

  1. 在客户端上,您可以直接遍历数组,而不必提前担心其中包含哪个 id,即无需硬编码。
  2. @JBNizet所指出的那样,基于数组的方法将保持其顺序。

缺点:如果您想获取单个 id,则需要遍历数组。

通常我们不会在客户端发送太多信息,因此基于数组的方法不会造成任何问题。并且,如果您想要基于 id 的方法,则可以在两个方面(服务器和客户端)将数组转换为 Map


这些是不错的见解,但我更关心服务器会发生什么。 - me_digvijay
2
硬编码部分并不是真正的问题。您也可以使用for(key in obj)迭代对象,并使键值可配置。但我怀疑这甚至并不必要。 - maja
@maja,在这种情况下,两种方法都是相同的,你在两种情况下都进行了迭代。 - Naman Gala
@maja,你说得对,我们也不应该担心客户端性能。 - Naman Gala
@NamanGala 这就是为什么我将其发布为评论而不是答案^^。对于客户端来说,数据的呈现方式完全无关紧要。只有在对象的情况下,网络开销会稍微大一些,特别是如果ID非常长。真正重要的是语义。 - maja
显示剩余3条评论

7
在服务器端,数组被存储为简单的列表:ArrayList<Content>,而对象则被存储为映射:HashMap<String, Content>或大多数情况下存储为Java对象。
为了将Java实体转换为JSON并从JSON中转换回来,您可以查看Jackson项目,该项目可以为您完成所有这些操作。
我不会担心这两种变体之间的任何性能差异。更重要的是拥有一个可理解的语义API,因此您应该基于业务案例而不是性能来做出决策。
从你的例子来看,我认为Array是更好的方法,因为你想返回一组相同的用户。我认为发送两次id没有意义,而且增加了必须传输的数据量。
此外,由于在Java中存储和迭代Arrays要简单得多,因此它们应该比对象提供更好的性能。
一些常见的区别:
  • 数组保留顺序。
  • 数组可以包含重复的条目。
  • 对象通常具有更大的存储/网络开销。
  • 数组在迭代时更快(在服务器端)。

4
除了以上的技术差异外,我认为对象和数组在目的和意义上存在根本区别。
1. 对象的属性描述或定义对象,而 2. 数组的元素并不描述或定义数组,相反,数组定义了其内容。 请注意 - 我讨论的不是技术方面。从语义上讲,每个元素都有自己的目的,技术上可以有任何组合。
例如,一个卡片持有者。每张卡片都不能描述或定义卡片持有者。但是卡片持有者确实定义了它的用途 - 只能容纳卡片。
对象用于表示实体及其属性,属性描述或定义实体。以同样的卡片为例。卡片具有颜色、数字等属性,这些属性描述或定义了卡片的特征。
针对你上面的示例:
1. 每个表示人的对象由属性id、firstName和lastName定义。 2. 人员列表不能是对象的对象,因为每个ID并不描述对象的对象。因此,
"users":[ { "id":"id", "key2":"value2", "key3":"value3" }, { "id":"id", "key2":"value2", "key3":"value3" } ]

原先示例中的表述更好。
"users": {
    "id1": {
        "id": "id1",
        "firstname": "firstname1",
        "lastname": "lastname1"
    },
    "id2": {
        "id": "id2",
        "firstaame": "firstname2",
        "lastname": "lastname2"
    }
}

尽管从技术上讲,您可以使用任一种方式。 我希望我能够以正确的方式表达我的想法。

2
我可以知道为什么要负评吗?我觉得 StackOverflow 应该强制要求在负投票时添加评论,以便人们意识到自己的错误。 - wallop

2

在JavaScript中,您可以使用object[property]表示法来访问或设置对象的属性。

在后端使用基于数组的方法,并在前端将数组转换为Map(也称为基于JSON的方法)。

var list = [{id: "id1", value: "One"}, {id: "id2", value: "Two"}]
var map = {};
list.forEach(function (item) { map[item.id] = item });
map.get("id1")

如果你的列表发生了变化,你可以从后端获取新的列表,并在UI中更新你的地图。
这样做可以使你的后端更快地响应,因为它不需要将列表转换为地图。你的前端将会对列表进行一次O(n)迭代来将其转换为地图。但与每次在列表上搜索时所需的O(n)相比,这是一个小小的代价。
如果你将在后端主要进行按id获取数据,请使用基于JSON的后端(你可以使用LinkedHashMap来保持顺序)。

1
两种方法各有优缺点,取决于您所关注的内容。
数组方法易于序列化,并更加“框架”友好(您可以将bean添加到列表中并对其进行序列化,完成后即可)。例如,Web容器可以在不需要任何自定义的情况下返回响应。这很可能会被大多数框架直接支持。
另一方面,基于对象的方法更难生成(相对而言),但是如果已知键,则更易查找。
因此,为了生产者的实现便捷性,请选择基于数组的方法。为了客户端使用的便利性,请选择基于对象的方法。

1
你的第一种“基于JSON”的表示法有一个很大的缺点,某些框架在(反)序列化时会遇到问题。例如,DataContractSerializer(C# .NET)将期望在对象类users中定义(硬编码)字段id1id2。我不确定这是否也适用于某些Java框架,也许你使用的框架可以将其反序列化为HashMap。总的来说,当涉及迭代等操作时,我认为数组表示法更加直观易懂。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接