最佳实践是从Restful服务返回Java对象,而不是手动构建JSON返回。

huangapple 未分类评论44阅读模式
英文:

Best practice when returning from Restful services - returning Java Object vs returning manually constructed JSON

问题

我目前正在开发返回List<ConfidentialData>的RESTful Web服务。(我将使用ConfidentialData作为此问题的示例)

假设ConfidentialData定义如下:

@Getter
@Setter
public class ConfidentialData {
    private Integer id; // 唯一标识符
    private String data;
    private String creationDate;
    private String approvalDate;
}

现在,我正在使用Jackson将这个List<ConfidentialData>转换为JSON,并将其作为Response发送。

现在,UI中的不同组件需要ConfidentialData的不同状态。假设我的某个UI页面(称为page1)需要纯粹的ConfidentialData对象(JSON中没有任何额外的成员),而另一个页面(称为page2)需要带有一些附加成员的ConfidentialData对象(假设这些成员与ConfidentialData的某些统计信息有关。这些统计数据实际上不属于ConfidentialData对象,但当page2请求时,需要将其添加到JSON中)。

我有3种选择:

  • 为page1和page2构造单独的领域对象。
    • 我担心这个解决方案在可扩展性方面不是很好,因为可能会有更多页面需要稍微不同的ConfidentialData组合,这样会使我的领域对象变得庞大。
  • 只保留一个单一的领域对象,并构造JSON - 通过添加特定页面所需的附加成员。
    • 我可以看出,这种情况下我需要处理JSON。(但我也知道,存在像GSON这样的复杂库,可以让我的工作变得容易)
  • 我可以简单地创建一个单一的领域对象,其中包含page1、page2、page3等所需的一切内容。(并且在需要时,我会继续向这个ConfidentialData领域对象添加任何附加成员)
    • 我非常反对这种方法,因为我们要讨论的机密数据的附加成员不容易计算。在某些情况下,它可能是与ConfidentialData相关的某些统计数据,计算这些统计数据将会是计算成本昂贵的。当UI永远不会使用它时(例如在page1的情况下),我不希望我的简单API调用执行所有这些计算。

我可以看到第一种和第二种方法的明显缺点。
我的问题是,在处理这种情况时,RESTful服务中的良好做法是什么。

为什么不操纵JSON:

  • 另外,我不太喜欢使用JSON,因为我们Java的权限过滤器(这是一个拦截器,它拦截来自服务的响应,并根据用户的权限对列表进行一些过滤)将不得不调整JsonArray以进行过滤,而不是简单地对List<ConfidentialData>进行过滤。
  • 但考虑到我们有像GSON这样复杂的库,过滤可能会很容易。
  • 另外,由于过滤只基于ConfidentialData#getId()(并且这永远不会改变),我可以考虑采用基于JSON的方法,目前看来在可扩展性方面很有前途。

我可以看到这是在操作JSON和创建多个领域对象之间的权衡。在业界是否有遵循的标准来处理这种情况呢?

英文:

I'm currently working on restful web services that returns, say a List&lt;ConfidentialData&gt;. (I'm using this ConfidentialData as an example for this question)

Suppose that this ConfidentialData is defined as follows:

@Getter
@Setter
public class ConfidentialData {
    private Integer id; // unique-identifier
    private String data;
    private String creationDate;
    private String approvalDate;
}

Now, I'm using jackson which behind the scene converts this List&lt;ConfidentialData&gt; to JSON and sends it as Response.

Now, different components in UI requires different state of ConfidentialData. Let's suppose that one of my UI pages (say page1) require the pure ConfidentialData object (without any additional members in JSON), and another page (say page2) requires ConfidentialData object with some additional members (Say these members are related to some statistics of ConfidentialData. These statistics don't really belong to the ConfidentialData object, but are to be added when page2 asks for it).

I've 3 options to go about it:

  • Construct a separate domain object for page1 and page2.
    • I'm afraid that this solution is not very scalable as there can be more page that required slightly different composition of ConfidentialData and I'll end up bloating up my domain objects.
  • Just keep one single domain object and construct JSON - by adding additional members that are required by specific pages.
    • I can see that I'll have to play with JSON in this case. (But I'm also aware of the fact that there exists sophisticated libraries like GSON that will make my life easy)
  • I can can simply create one single domain object that will contain everything that's required by page1, page2, page3 and so on. (And I'll keep adding any additional members to this ConfidentialData domain object as and when required)
    • I'm very much opposed to this approach as the additional members that we're talking about with confidential data aren't easy to calculate. In some cases it can be some statistics related to ConfidentialData and it'll be computationally expensive to calculate those statistics. I don't want my simple API call to do all this computation, when the UI won't ever use it (eg. in case of page1)

I can see obvious drawbacks of both the first and the second approach.
My question here is what is the good practice in terms of restful services to handle such a situation.

Why not manipulate the JSON:

  • Also, I'm not very much in favor of using JSON, as our java's permissions-filter (which is an interceptor - which intercepts the response from the services, and does some filtering on the list based on user's permissions) will then have to tweak JsonArray for doing the filtering, instead of simply filtering List&lt;ConfidentialData&gt;.
  • But given that we've sophisticated libraries like GSON, the filtering can be easy.
  • Also, as the filtering is to be done only on the basis of ConfidentialData#getId() (and this is never going to change) I can think of going ahead with JSON based approach which at the moment looks promising in terms of scalability.

I can see it as a trade-off between manipulating JSON and creating multiple domain objects. Is there any standard that's followed in industry to handle this kind of situation?

答案1

得分: 0

根据您的服务调用方式,您可以仅填充ConfidentialData的相应属性,保持其他属性不变。在序列化过程中,您可以省略任何未设置的属性。这可以通过提供序列化库(无论是Jackson还是Gson)的适当元数据来实现。

英文:

Depending on how your service has been called, you can populate only corresponding properties of the ConfidentialData and leave others intact. During serialization you can omit any unset properties. This can be achieved by supplying appropriate metadata of serialization library, be it Jackson or Gson.

huangapple
  • 本文由 发表于 2020年4月10日 13:48:09
  • 转载请务必保留本文链接:https://java.coder-hub.com/61134696.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定