对象数组与对象对象

Array of objects vs Object of Objects

问题是决定以下符号之间的权衡:

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"
    }
]

关于同一问题上的 this post,我决定(在前端)使用 JSON 对象符号而不是对象数组,因为它符合我的要求更好的性能和更少的浏览器代码。

但问题是列表本身不是静态的。我的意思是列表正在生成,即从 DB (NoSQL) 生成 fetched/stored,并通过服务器上的 Java API 为新条目创建。我无法决定我应该在后端使用哪种表示法(最终也会影响 UI )。

任何 thoughts/suggestion 关于性能、可维护性或可伸缩性的信息都将受到赞赏。

这是一个完全基于意见的问题。可能还有很多其他的要点,但我可以指出如下。

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

优点:在JavaScript中可以直接使用users.id1,​​users.id2即不需要迭代

缺点: 在客户端,您将如何要求 JSON 中存在的 ID,即硬编码或使用一些动态方法来告诉您您的 JSON.

中存在哪个 ID

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

优点:

  1. 客户端可以直接遍历数组,不用 提前担心其中存在哪个 id 即不难 编码。
  2. 正如 @JBNizet 所指出的,基于数组的方法将保持顺序。

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

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

在服务器端,数组存储为简单的列表:ArrayList<Content>,而对象要么存储为映射:HashMap<String, Content>,要么主要存储为 Java 个对象。

为了将 Java 实体与 JSON 相互转换,您可以查看 Jackson 项目,它为您完成了所有这些工作。

我不担心这两个变体之间的任何性能差异。更重要的是具有可理解的语义 API,因此您应该根据业务案例而不是性能来做出决定。

看看你的例子,我认为 Array 是更好的方法,因为你想要 return 一个全部平等的用户列表。两次发送 id 毫无意义,并且会增加必须传输的数据量。

此外,由于 Arrays 在 Java 中更易于存储和迭代,因此它们也应该提供比对象更好的性能。

一些一般差异:

  • 数组保持顺序
  • 数组可以包含重复条目
  • 对象通常有更大的storage/network开销
  • 数组迭代速度更快(在服务器端)

您想到的第一个 "JSON based" 表示法的一大缺点是某些框架在(反)序列化方面会有问题。例如,DataContractSerializer (C# .NET) 将期望字段 id1id2 在对象 users 的 class 中定义(硬编码)。我不确定这是否也适用于某些 Java 框架。也许您将使用的框架可以将其反序列化为 HashMap。

总而言之,我发现在迭代等方面使用数组表示法更直观。

您可以使用 object[property] notation 访问或设置 JavaScript 中对象的属性。

在后端使用 基于数组的 方法,并将数组转换为映射(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) 相比,这是一个很小的代价。

如果您主要在后端对您的数据进行 get by id,请在后端本身使用 JSON Based(您可以使用 LinkedHashMap 以保持顺序)。

这两种方法各有利弊,具体取决于您所关注的是什么。

数组方法易于序列化并且更 'framework' 友好(您可以将 bean 添加到列表并序列化列表,然后就完成了)。例如,这允许 Web 容器 return 响应而无需任何自定义。大多数框架可能开箱即用地支持这一点。

另一方面,基于对象的方法更难生成(相对而言),但如果密钥已知,则更容易查找。

因此,为了便于实施(由生产者),请选择基于数组的方法。为了易于使用(由客户使用),请使用基于对象的方法。

除了上述所有技术差异外,我认为对象和数组的用途和含义也存在根本差异。

  1. 对象的属性DESCRIBE/DEFINE对象而
  2. 数组的元素不是DESCRIBE/DEFINE数组,相反,数组定义了它的内容。 请注意 - 我不是在谈论技术方面。您可以在技术上有任何组合,但在语义上每个组合都有其目的。

    • 比如名片夹。每张卡 不是 DESCRIBE/DEFINE 持卡人。但是持卡人确实定义了它只持有卡片的目的/

    • 一个对象用来表示一个实体及其属性DESCRIBE/DEFINE实体。以卡片为例。卡片具有颜色、数字等属性,DESCRIBE/DEFINE 卡片是什么。

对于你上面的例子:

  1. 代表一个人的每个对象 由属性 id、firstName 和 lastName 定义。

  2. 这些人的列表不能是objects of objects因为每个id都没有描述objects of objects。所以

    "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"
    }
}

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