最近我偶然发现了我的新团队大量使用JsonObject进行休息数据交换的情况。他们的观点是在使用pojo时我们与其他服务紧密绑定,而jsonObject提供自由。此外,它还可以节省不必要的数据序列化,同时大大减少了类的数量。
我有一些要点可以解决它们:
@JsonIgnore
我不确切地知道反序列化的成本,但不知怎的,我觉得它不应该有太大区别。
有人可以帮我理解哪种观点是可行的吗?
请提供使用POJO和JSONObject的一些优缺点。
由于
答案 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:
@Transient
关键字来简单地进行处理,但是如果您使用了JsonObject,将会需要一些代码更改。)@JsonInclude(Include.NON_EMPTY)
来使用pojos轻松实现。使用JsonObject:
答案 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的时间。