我应该使用POJO或JSONObject进行REST调用

时间:2018-01-12 10:26:38

标签: java json serialization jackson

最近我偶然发现了我的新团队大量使用JsonObject进行休息数据交换的情况。他们的观点是在使用pojo时我们与其他服务紧密绑定,而jsonObject提供自由。此外,它还可以节省不必要的数据序列化,同时大大减少了类的数量。

我有一些要点可以解决它们:

  1. Pojo为数据提供了更多的含义,我们使用正确的数据类型保存数据。
  2. 如果我们只需要10个json字段中的2个字段,我们可以使用@JsonIgnore
  3. 反序列化为2个字段类

    我不确切地知道反序列化的成本,但不知怎的,我觉得它不应该有太大区别。

    有人可以帮我理解哪种观点是可行的吗?

    请提供使用POJO和JSONObject的一些优缺点。

    由于

6 个答案:

答案 0 :(得分:8)

我发现拥有pojos有以下优点

1)可读性-您将不会真正了解复杂json的结构。编写一个简单的get将需要知道json的结构。请在此处参考我的文章的“基于JSON对象的POJO”-> https://medium.com/tech-tablet/programming-went-wrong-oops-38d83058885

2)提供类型检查-我们可以轻松地将Cat分配给Dog,甚至在运行时甚至都不知道。

3)通过组合和封装感觉更加面向对象-使用POJO可以轻松理解设计师的观点。是具有HAS-A车轮的IS-A车辆的汽车。

4)您可以选择要反序列化的内容,并且仅将其保留在内存中-当使用JSON对象反序列化刚刚通过网络接收到的对象时,无法选择要反序列化和存储的内容进入记忆。如果您有一个1 MB大小的对象,其中只有200字节是您的有效负载,那么如果不使用POJO,我们最终将整个1 MB对象保存在内存中。

5)允许使用集合并以清晰的方式对其进行流操作-JsonNode中不存在对流操作的本机支持。我们将需要使用可以避免的StreamStupport对象。

6)允许跨框架引用。通过一些注释,您可以选择将特定字段映射到数据库客户端-在为数据库使用ORM框架时,很容易注释实体并将其映射到数据库模式。

7)自然支持设计模式

8)最小化非本机依赖性-为什么必须使用本机Java中本身没有的JsonNode或等效项?尤其是如果它具有上述缺点。

如果您担心pojo附带的仪式(例如具有吸气剂,塞特塞等),请查看“龙目岛”。该库将帮助您以简洁的方式创建pojos,并仍然获得上述好处。

另一方面,如果您要处理的是难以更改的旧API,该API会以动态变化的响应进行响应,那么JsonNode是一个快速的候选人。

答案 1 :(得分:6)

这实际上取决于您的应用程序的情况和性质。如果您接收的数据没有固定的结构/字段名称/数据类型,或者它正在发生变化,那么当然使用JsonObject会更有意义。

另一方面,如果它是固定结构并且涉及访问字段的操作,那么最好使用pojo。它具有更好的可读性IMO。

答案 2 :(得分:3)

取决于情况:

  • 使用Pojo:

    1. 如果数据字段像它们的名称一样固定,请键入Pojos,因为它将清晰易读。
    2. 如果在很多地方使用重构,将更容易。
    3. 如果要将这些数据持久保存在db中,那么修改数据也将很容易。假设您的pojo中有一个数据在执行计算时使用,但是您不想将其保存在db中(因此您可以通过在Java中使用@Transient关键字来简单地进行处理,但是如果您使用了JsonObject,将会需要一些代码更改。)
    4. 假设您不想在响应中传递空值,则可以通过在Java中使用@JsonInclude(Include.NON_EMPTY)来使用pojos轻松实现。
  • 使用JsonObject:

    1. 如果数据字段的类型或结构等类型不固定,那么您将无法在pojo中进行映射。

答案 3 :(得分:0)

我要添加:

  • 使用POJO可以使用构建器模式。

  • 将来的重构将更加容易。假设您有一个Person类,并且在代码中的许多地方都使用了该类。如果您的Person类需要更改其字段之一,那么您可以轻松找到在何处进行更改。

  • 使用POJO使您的代码与您的域更加紧密。如果您正在为汽车公司编写代码,则将具有诸如Car,Wheels,Engine等类。您的代码将变得更具可读性和可测试性。

答案 4 :(得分:0)

  

他们的观点是,在使用pojo时,我们与rest服务紧密绑定,而jsonObject提供了自由。

问他们这种自由需要多长时间? API模型会一直变化吗?它会在某个时候安定下来。另外,它是如何紧密结合的?如果您不确定模型的某个部分,则可以为该部分创建一个通用对象,这将为您提供所需的灵活性。

  

它还避免了不必要的数据序列化,同时大大减少了类的数量。

我认为没有必要。直接使用JsonObject很麻烦。 关于减少类的数量,无论如何,您都应该为正在交换的数据提供一些模型类。它更加清晰。如果使用的是Swagger,它将添加到REST端点的规范中。 Swagger自动创建表单以根据数据模型输入数据。 API变得更易于维护(不需要额外的文档)。测试变得更加容易。

  

我不知道反序列化的确切成本,但是我觉得它应该没有太大区别。

唯一可以确定的是基准测试。您可以以此为起点来了解并比较当前的实现https://github.com/fabienrenaud/java-json-benchmark

答案 5 :(得分:0)

该参数实际上归结为您要对处理的数据使用POJO还是Maps,因为这是两种处理数据样式之间的根本区别。

JsonObject(from jee7)只是一个Map(实际的类型签名扩展了Map<String, JsonValue>)。

使用POJO(例如,使用Jackson反序列化)是真实对象。

因此,如果您通常不对数据使用域/模型类,那么我猜一个Map就可以了。如果您这样做(像大多数开发人员一样),则最好将此实践扩展到您的API合同。

要解决特定问题:

  

JsonObject避免了不必要的数据序列化,同时大大减少了类的数量。

不需要,这两个JSON API都需要序列化/反序列化,这是将有线数据转换为对象的过程。我敢打赌,Jackson比JsonObject更快,但是正如Satyendra Kumar指出的那样,基准测试将以某种方式证明这一点。

  

在使用pojo时,我们与其余服务紧密绑定,而jsonObject提供了自由

如果您使用的是来自API的数据,那么您将绑定到数据模型,无论是通过属性foo还是response.getFoo()response.get("foo")来获取数据。

要对类与映射之间的权衡进行真正全面的讨论,请check out this SoftwareEngineering post

值得指出的是,使用Jackson / POJO并不意味着您与本地的REST响应模型紧密相关。 Jackson对Tolerant Reader模式提供了出色的支持,这意味着API响应中的新字段不会破坏反序列化,并且提供了诸如@JsonCreator@JsonValue@JsonIgnore之类的注释用于将API响应映射回您的本地域模型。

它还提供了用于处理集合和泛型的强大工具。

最后,如果您要与之交互的服务既庞大又复杂,如果它们提供了摇摇欲坠的规范,那么您可以基于该规范generate the models,这将大大减少整理POJO的时间。