我应该在REST调用中使用POJO还是JSONObject?

14

最近我遇到了一个情况,我的新团队在进行rest数据交换时大量使用JsonObject。他们认为使用POJO会与rest服务绑定得更紧密,而使用JsonObject则更加自由。同时,它可以避免不必要的数据序列化,同时大大减少了类的数量。

我有一些观点来反驳他们:

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

我不确定反序列化的成本是多少,但我有一种感觉,它应该没有太大的差别。

能否有人帮助我理解哪种观点是正确的?请提供使用POJO和JSONObject的一些优缺点。

谢谢

6个回答

14
我认为拥有POJOs有以下优点。
1. 可读性 - 你不会真正了解复杂json的结构。编写一个简单的get请求需要知道json的结构。请参考我在这里的文章中的“POJOs over JSON Objects”部分 -> https://medium.com/tech-tablet/programming-went-wrong-oops-38d83058885 2. 提供类型检查 - 我们可以轻松地将一只猫赋值给一只狗,甚至在运行时都不知道。
3. 通过组合和封装感觉更面向对象 - 使用POJO可以很容易地理解设计师的视角。一辆车是一种车辆,拥有一个轮子。
4. 您可以选择要反序列化的内容,并仅将其保留在内存中 - 当我们对刚刚从网络接收到的对象进行反序列化时,使用JSON对象无法选择要反序列化和存储到内存中的内容。如果您有一个1MB大小的对象,其中只有200字节是有效负载,如果我们不使用POJO,我们将最终将整个1MB对象保存在内存中。
5. 允许以可读的方式使用集合和流操作 - JsonNode没有原生支持流操作。我们需要使用一个StreamSupport对象,而这可以避免。
6. 允许跨框架引用。通过几个注解,您可以选择将特定字段映射到数据库客户端 - 当您为数据库使用ORM框架时,很容易注释和映射实体到数据库模式。
7. 自然支持设计模式
8. 最小化非本机依赖 - 为什么要使用不自带于原生Java的JsonNode或等效对象?特别是如果它具有上述缺点。
如果你对于像拥有getter、setter等这样的传统仪式感到担忧,不妨看看"Lombok"。这个库可以帮助你以简洁的方式创建你的pojos,并且仍然能够获得上述的好处。
另一方面,如果你正在处理一个难以更改的API,它会返回动态变化的响应,那么JsonNode是一个快速解决方案的候选者。

1
请问您能否详细解释一下上述所有要点? - Erran Morad
1
@BoratSagdiyev 我已经在上述要点中添加了解释。 - Prasanna

8

这真的取决于情况和您的应用程序的性质。如果您接收到的数据没有固定的结构/字段名称/数据类型或者它是不断变化的,那么使用JsonObject显然更合理。

另一方面,如果它具有固定的结构并涉及访问字段的操作,则最好选择pojo。我认为它的可读性更好。


5

根据情况而定:

  • 使用POJO:

    1. 如果数据字段固定,如它们的名称和类型,请使用POJO,因为它将清晰易读。
    2. 如果在多个地方使用,则重构将更容易。
    3. 如果要将此数据持久化到数据库中,则修改数据也将变得容易。假设您的POJO中有一个数据,在执行计算时使用,但您不想将其保存在数据库中(所以您可以简单地使用@Transient关键字在Java中实现,但如果您使用JsonObject,则需要进行一些代码更改)。
    4. 假设您不想在响应中传递空值,您可以轻松使用POJO来使用@JsonInclude(Include.NON_EMPTY)在Java中实现。
  • 使用JsonObject:

    1. 如果数据字段不固定,例如类型或结构,则无法将其映射到POJO中。

2
我想补充一点:
  • 使用POJOs,你可以使用构建器模式。

  • 将来的重构会更容易。想象一下,你有一个名为Person的类,在代码中的许多地方都会用到这个类。如果你的Person类需要更改其中一个字段,那么你可以很容易地找到要更改的地方。

  • 使用POJOs可以使你的代码与你的领域更加协调。如果你正在编写为汽车公司编写的代码,你将拥有像Car、Wheels、Engine等类。你的代码将变得更加可读和可测试。


最初的回答: - POJO是指普通Java对象,没有任何限制或强制性规则,可以使用构建器模式。 - 使用POJO将使将来的重构更加容易,因为你可以轻松找到在哪里需要修改。 - 使用POJO可以使你的代码更符合你的领域。例如,如果你正在编写汽车公司的代码,你可以创建Car、Wheels、Engine等类,从而使你的代码更易读,更易于测试。

2
这个论点实际上归结为你想要使用POJO还是Map来处理数据,因为这是处理数据的两种风格之间的根本区别。
JsonObject(来自 jee7)只是一个Map(实际类型签名扩展了 Map)。
使用POJO(例如使用Jackson反序列化)是真正的对象。
所以如果你通常不使用领域/模型类来处理数据,那么我想一个Map就可以了。如果你这样做(像大多数开发人员一样),那么将这种做法扩展到你的API合同中是个好主意。
针对具体的观点:
JsonObject可以避免不必要的数据序列化,同时大大减少类的数量。
它们都需要序列化/反序列化,也就是将数据转换为对象的过程。我敢打赌Jackson比JsonObject更快,但正如Satyendra Kumar所指出的那样,基准测试可以证明其中一种方式更好。如果您从API使用数据,那么无论通过response.getFoo()还是response.get("foo")从属性foo中获取数据,您都与数据模型绑定。关于类和映射之间权衡的全面讨论,请查看此SoftwareEngineering帖子
值得指出的是,使用Jackson/POJO并不意味着你与REST响应的本地模型紧密耦合。Jackson对Tolerant Reader模式有很好的支持,这意味着API响应中的新字段不会破坏反序列化,并且有一些注释,如@JsonCreator@JsonValue@JsonIgnore用于将API响应映射回本地领域模型。
它还提供了处理集合和泛型的强大工具。
最后,如果你正在与一个庞大而复杂的服务交互,如果他们提供了swagger/raml规范,那么你可以根据该规范生成模型,这应该大大减少维护POJO所需的时间。

1
他们的观点是,使用pojo会与rest服务绑定得更紧密,而jsonObject则更自由。请问这种自由需要多久?API模型会一直改变吗?它最终会稳定下来。此外,它是如何绑定得更紧密呢?如果您对模型的某个部分不确定,可以为该部分创建一个通用对象,这将给您带来所需的灵活性。
此外,它还可以节省不必要的数据序列化,同时大大减少了类的数量。但我认为这并不是不必要的。直接使用JsonObject只会让事情变得繁琐。关于减少类的数量,您应该无论如何都需要一些用于交换数据的模型类。这会使事情更清晰。如果您正在使用Swagger,它将增加REST端点的规范。Swagger会根据数据模型自动创建输入数据的表单。API变得更容易维护(无需额外的文档)。测试也变得更容易。
我不确定反序列化的成本,但我有一种感觉,它应该没有太大的区别。
唯一确定的方法是基准测试。您可以使用此作为起点,以获得洞察力并比较当前实现https://github.com/fabienrenaud/java-json-benchmark

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