简体   繁体   English

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

[英]Shall I use POJO or JSONObject for REST calls

Recently I have stumbled upon a situation where my new team is heavily using JsonObject for doing rest data interchange. 最近我偶然发现了我的新团队大量使用JsonObject进行休息数据交换的情况。 Their view is while using pojo we are binding tightly with the rest service, while jsonObject gives freedom. 他们的观点是在使用pojo时我们与其他服务紧密绑定,而jsonObject提供自由。 Also it saves from unnecessary data serialisation at the same time reducing number of classes heavily. 此外,它还可以节省不必要的数据序列化,同时大大减少了类的数量。

I have some points to encounter them as: 我有一些观点可以解决它们:

  1. Pojo gives more meaning to data and we are holding data with correct data type. Pojo为数据提供了更多的含义,我们使用正确的数据类型保存数据。
  2. If we need only 2 fields of 10 fields of json, we can deserialize to 2 fields class with @JsonIgnore 如果我们只需要10个json字段的2个字段,我们可以用@JsonIgnore反序列化为2个字段类

I don't know exactly on the cost of deserialisation, but somehow I have a feeling it shouldn't be much difference. 我不确切知道反序列化的成本,但不知怎的,我觉得它应该没有多大区别。

Can someone help me understand which perspective is way to go ? 有人可以帮我理解哪种观点是可行的吗?

Please provide some pros and cons of using POJO and JSONObject. 请提供使用POJO和JSONObject的一些优缺点。

Thanks 谢谢

I see the following advantages in having pojos 我看到pojos有以下优点

1) Readability - You will not really know the structure of a complex json. 1)可读性 - 你不会真正了解复杂json的结构。 writing a simple get will require one to know the structure of the json. 写一个简单的get将需要一个知道json的结构。 Please refer to the "POJOs over JSON Objects" section of my article here -> https://medium.com/tech-tablet/programming-went-wrong-oops-38d83058885 请参阅我的文章中的“POJO over JSON Objects”部分 - > https://medium.com/tech-tablet/programming-went-wrong-oops-38d83058885

2) Offers Type Checks - We could easily assign a Cat to a Dog and not even know about it till runtime. 2)提供类型检查 - 我们可以轻松地将猫分配给狗,直到运行时才知道它。

3) Feels more object-oriented with Composition & encapsulation - It's easy to understand the designer's perspective with a POJO. 3)使用Composition和encapsulation感觉更加面向对象 - 使用POJO很容易理解设计者的观点。 A Car which IS-A Vehicle that HAS-A Wheel. 一辆车是一辆A-A车辆。

4) You could choose what you wanna deserialize and keep only that in memory - When deserializing the object that we have just received over the network, with a JSON Object, there is no way to choose what has to be deserialized and stored into memory. 4)您可以选择要反序列化的内容并仅将其保留在内存中 - 当通过网络反序列化我们刚收到的对象时,使用JSON对象时,无法选择必须反序列化并存储到内存中的内容。 If you have an object of 1 MB size where only 200 Bytes is your payload, we will end up holding the entire 1 MB object in memory if we don't use POJOs. 如果你有一个1 MB大小的对象,你的有效负载只有200 Bytes,如果我们不使用POJO,我们最终会将整个1 MB对象保留在内存中。

5) Allows collection to be used and stream operations on them in a legible way - There is no native support for stream operations in a JsonNode. 5)允许使用集合并以清晰的方式对它们进行流操作 - 在JsonNode中没有对流操作的本机支持。 We will need to use a StreamStupport object which could be avoided. 我们需要使用可以避免的StreamStupport对象。

6) Allows cross framework referencing. 6)允许跨框架引用。 With a few annotations, you can choose to map specific fields to a database client - When you use an ORM framework for you database, it's easy to annotate and map entities to the database schema. 通过一些注释,您可以选择将特定字段映射到数据库客户端 - 当您为数据库使用ORM框架时,可以轻松地对实体进行注释并将实例映射到数据库模式。

7) Naturally supports design patterns 7)自然支持设计模式

8) Minimalizing non-native dependencies - Why do you have to use a JsonNode or equivalent that does not come by itself in native Java? 8)最小化非本机依赖关系 - 为什么你必须使用本机Java中不能自带的JsonNode或等价物? Especially if it has the above disadvantages. 特别是如果它具有上述缺点。

If you are concerned about the rituals that come with a pojo like having getters, setters etc, take a look at "Lombok". 如果你担心像有吸气鬼,定居者等的pojo所带来的仪式,请看看“龙目岛”。 This library will help you create your pojos in a concise way and still reap the above benefits. 该库将帮助您以简洁的方式创建您的pojos,并仍然获得上述好处。

On the other hand if you are are dealing with a hard to change legacy API that responds with a dynamically changing response, JsonNode is a quick win candidate. 另一方面,如果您正在处理难以更改的遗留API,并且响应动态变化的响应,则JsonNode是一个快速获胜的候选者。

It really depends on the situation and the nature of your application. 这实际上取决于您的应用程序的情况和性质。 If the data your are receiving has no fixed structure/field names/data types or it is ever changing then of course using JsonObject makes more sense. 如果您接收的数据没有固定的结构/字段名称/数据类型,或者它正在发生变化,那么当然使用JsonObject会更有意义。

On the other hand, if it is of fixed structure and involves operations which access the fields, its better to go with pojo. 另一方面,如果它是固定结构并涉及访问字段的操作,那么最好使用pojo。 It has better readability IMO. 它具有更好的可读性IMO。

Depends on circumstances: 取决于具体情况:

  • Use Pojo : 使用Pojo:

    1. If the data fields are fixed like their name, type use Pojos, as it will be clear and easily readable. 如果数据字段的名称是固定的,请键入use Pojos,因为它很清晰且易于阅读。
    2. Refactoring will be easier if it is used in many places. 如果在许多地方使用重构将更容易。
    3. If you want to persist this data in db then modification of data will also be easy. 如果要在db中保留此数据,那么修改数据也很容易。 Suppose there is a data in your pojo which is used while performing calculation, but you don't want save it in db ( so you can simply do it by using @Transient keyword in java, but if you have used JsonObject this would have required some code changes). 假设你的pojo中有一个数据在执行计算时被使用,但是你不想把它保存在db中(所以你可以通过在java中使用@Transient关键字来实现它,但如果你使用了JsonObject,那么这就需要了一些代码更改)。
    4. Suppose you don't want to pass null values in the response, you can easily do it using pojos by using @JsonInclude(Include.NON_EMPTY) in java. 假设您不想在响应中传递空值,您可以使用@JsonInclude(Include.NON_EMPTY)在java中使用@JsonInclude(Include.NON_EMPTY)轻松完成。
  • Use JsonObject: 使用JsonObject:

    1. If data fields are not fixed like their type or structure, so you won't be able to map it in pojo. 如果数据字段没有像其类型或结构那样修复,那么您将无法在pojo中映射它。

I want to add: 我想补充一下:

  • with POJOs you can use the builder pattern. 使用POJO,您可以使用构建器模式。

  • future refactors will be more easy. 未来的重构会更容易。 Imagine you have a class Person, and you use this class in many places in your code. 想象一下,你有一个Person类,你在代码中的很多地方使用这个类。 If your Person class needs to change one of its fields, then you can find easily where to change it. 如果您的Person类需要更改其中一个字段,那么您可以轻松找到更改它的位置。

  • using POJOs makes your code more cohesive with your domain. 使用POJO可以使您的代码与您的域更具凝聚力。 If you are writing code for a car company, you will have classes like Car, Wheels, Engine, etc. Your code will become more readable and testable. 如果您正在为汽车公司编写代码,您将拥有汽车,车轮,引擎等类。您的代码将变得更易读和可测试。

Their view is while using pojo we are binding tightly with the rest service, while jsonObject gives freedom. 他们的观点是在使用pojo时我们与其他服务紧密绑定,而jsonObject提供自由。

Ask them for how long this freedom is required? 问他们这需要多长时间? Is the API model going to change always? API模型总是会改变吗? It WILL settle down at some point. 它会在某个时候安定下来。 Also, how is it binding tightly? 另外,它是如何紧密绑定的? If there is some part of the model that you are not sure of, you can create a generic object for that part, that will give you as much flexibility as you want. 如果模型的某些部分您不确定,则可以为该部件创建一个通用对象,这将为您提供所需的灵活性。

Also it saves from unnecessary data serialisation at the same time reducing number of classes heavily. 此外,它还可以节省不必要的数据序列化,同时大大减少了类的数量。

I don't think it is unnecessary. 我不认为这是不必要的。 Using JsonObject directly is simply cumbersome. 直接使用JsonObject非常麻烦。 About reducing the number of classes, you should anyway have some model class for data that is being exchanged. 关于减少类的数量,你应该为正在交换的数据设置一些模型类。 It gives more clarity. 它更清晰。 If you are using Swagger, it will add to the specification of your REST endpoints. 如果您使用的是Swagger,它将添加到REST端点的规范中。 Swagger automatically creates forms to enter data based on the data model. Swagger自动创建表单以根据数据模型输入数据。 API becomes easier to maintain (no extra documentation required). API变得更容易维护(无需额外的文档)。 Testing becomes easier. 测试变得更容易。

I don't know exactly on the cost of deserialisation, but somehow I have a feeling it shouldn't be much difference. 我不确切知道反序列化的成本,但不知怎的,我觉得它应该没有多大区别。

The only way to be sure is benchmarking. 唯一可以肯定的是基准测试。 You can use this as a starting point to get an insight and compare the current implementation https://github.com/fabienrenaud/java-json-benchmark . 您可以将此作为一个起点,以获得洞察力并比较当前的实现https://github.com/fabienrenaud/java-json-benchmark

This argument really boils down to whether you want to use POJOs or Maps for the data you are dealing with, as that is the fundamental difference between the 2 styles of handling data. 这个论点实际上归结为您是否想要使用POJO或Maps来处理您正在处理的数据,因为这是两种处理数据样式之间的根本区别。

JsonObject ( from jee7 ) is just a Map (the actual type signature extends Map<String, JsonValue> ). JsonObject( 来自jee7 )只是一个Map(实际的类型签名扩展了Map<String, JsonValue> )。

Using POJO's (eg deserialised using Jackson ) are real objects. 使用POJO(例如使用Jackson反序列化)是真实的对象。

So if you dont use domain/model classes for your data normally then I guess a Map will do. 因此,如果您通常不使用域/模型类的数据,那么我猜Map会做。 If you do (like most developers would), then it's a good idea to extend this practice to your API contracts. 如果你这样做(像大多数开发人员那样),那么将这种做法扩展到API合同是个好主意。

To address specific points: 解决具体问题:

JsonObject saves from unnecessary data serialisation at the same time reducing number of classes heavily. JsonObject可以同时减少不必要的数据序列化,从而大大减少了类的数量。

It doesn't, both of these JSON API's require serialisation/deserialisation, which is the process of turning wire data into an object. 它没有,这两个JSON API都需要序列化/反序列化,这是将线数据转换为对象的过程。 I would bet that Jackson is faster than JsonObject, however as Satyendra Kumar pointed out benchmarking is going to prove it one way or other. 我敢打赌杰克逊比JsonObject更快,但是Satyendra Kumar指出基准测试将证明它是这样或那样的。

while using pojo we are binding tightly with the rest service, while jsonObject gives freedom 在使用pojo时,我们与其他服务紧密绑定,而jsonObject提供自由

If you are using the data from the API you are bound to the data model, whether you get the data from a property foo by response.getFoo() or response.get("foo") . 如果您使用API​​中的数据,则绑定到数据模型,无论是通过response.getFoo()还是response.get("foo")从属性foo获取数据。

For a really comprehensive discussion on the tradeoffs between classes and maps, check out this SoftwareEngineering post 有关类和地图之间权衡的真正全面讨论, 请查看此SoftwareEngineering文章

It's worth pointing out that using Jackson/POJOs doesn't mean you are tightly coupled to your local model of a REST response. 值得指出的是,使用Jackson / POJO并不意味着您与本地REST响应模型紧密耦合。 Jackson has excellent support for the Tolerant Reader pattern, which means that new fields in the API response will not break deserialisation, and a bunch of annotations like @JsonCreator , @JsonValue , @JsonIgnore for mapping the API responses back to your local domain model. Jackson对Tolerant Reader模式有很好的支持,这意味着API响应中的新字段不会破坏反序列化,还有一些注释,如@JsonCreator @JsonValue@JsonIgnore @JsonCreator@JsonValue ,用于将API响应映射回本地域模型。

It also provides powerful tools for dealing with collections and generics. 它还提供了处理集合和泛型的强大工具。

Finally if the service you are interacting with is big and complex, if they provide a swagger/raml spec then you can generate the models based on that spec which should greatly reduce the time taken to curate the POJOs. 最后,如果您正在与之交互的服务又大又复杂,如果它们提供了一个swagger / raml规范,那么您可以根据该规范生成模型 ,这将大大减少策划POJO所需的时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM