我应该如何处理 RESTful API 中的对象层次结构?

发布于 2024-09-26 13:24:59 字数 1777 浏览 4 评论 0原文

我目前正在为现有 PHP 应用程序设计 API,为此正在研究 REST 作为一种明智的架构方法。

我相信我对关键概念有了合理的掌握,但我正在努力寻找任何解决过对象层次结构和 REST 问题的人。

问题是......

在[应用程序]业务对象层次结构中,我们有:

Users 
 L which have one-to-many Channel objects
 L which have one-to-many Member objects
 

在应用程序本身中,我们使用延迟加载方法根据需要使用这些对象的数组填充用户对象。我相信从面向对象的角度来看,这是对象聚合,但我已经看到了各种命名不一致的情况,并且不关心引发一场关于精确命名约定的战争。

现在,考虑一下我有一些松散耦合的对象,根据应用程序的需要,我可能/可能不会填充这些对象。

从 REST 的角度来看,我试图确定该方法应该是什么。这是我目前的想法(暂时只考虑 GET):

选项 1 - 完全填充对象:

GET api.example.com/user/{user_id}

读取 User 对象(资源)并返回 User 对象以及所有可能的 Channel 和 Member 对象- 加载并编码(JSON 或 XML)。

优点:减少对象数量,无需遍历对象层次结构
缺点:必须完全填充对象(昂贵)

选项 2 - 填充主对象并包含指向其他对象资源的链接:

GET api.example.com/user/{user_id}

读取用户对象(资源)并返回填充的用户对象用户数据和两个列表。

每个列表都引用适当的(子)资源,即

api.example.com/channel/{channel_id}
api.example.com/member/{member_id}
    

我认为这接近(或完全)超媒体的含义 - 客户端可以根据需要获取其他资源(只要我明智地标记它们)。

优点:客户端可以选择加载从属或其他方式,更好地将对象分离为 REST 资源
缺点:需要进一步访问才能获取辅助资源

选项 3 - 启用递归检索

GET api.example.com/user/{user_id}

读取 User 对象并包含指向子对象列表的链接,即

api.example.com/user/{user_id}/channels
api.example.com/user/{user_id}/members

/channels 调用将返回以下通道资源列表形式(如上):

api.example.com/channel/{channel_id}
    

优点:主要资源公开去哪里获取下属,但不公开它们是什么(更 RESTful?),不需要预先获取下属,下属列表生成器(/channels 和 /members)提供接口(类似方法),使响应更像服务。
缺点:现在需要三个调用才能完全填充对象

选项 4 - (重新)考虑 REST 的对象设计

我正在重新使用[现有]应用程序对象层次结构并尝试将其应用于 REST -或者更直接地,为它提供一个API接口。

也许 REST 对象层次结构应该有所不同,或者新的 RESTful 思维可能暴露了现有对象设计的局限性。

欢迎对上述任何想法。

I am currently designing the API for an existing PHP application, and to this end am investigating REST as a sensible architectural approach.

I believe I have a reasonable grasp of the key concepts, but I'm struggling to find anybody that has tackled object hierarchies and REST.

Here's the problem...

In the [application] business object hierarchy we have:

Users 
 L which have one-to-many Channel objects
 L which have one-to-many Member objects
 

In the application itself we use a lazy load approach to populate the User object with arrays of these objects as required. I believe in OO terms this is object aggregation, but I have seen various naming inconsistencies and do not care to start a war about the precise naming convention </flame war>.

For now, consider I have some loosely coupled objects that I may / may not populate depending on application need.

From a REST perspective, I am trying to ascertain what the approach should be. Here is my current thinking (considering GET only for the time being):

Option 1 - fully populate the objects:

GET api.example.com/user/{user_id}

Read the User object (resource) and return the User object with all possible Channel and Member objects pre-loaded and encoded (JSON or XML).

PROS: reduces the number of objects, no traversal of object hierarchies required
CONS: objects must be fully populated (expensive)

Option 2 - populate the primary object and include links to the other object resources:

GET api.example.com/user/{user_id}

Read the User object (resource) and return the User object User data populated and two lists.

Each list references the appropriate (sub) resource i.e.

api.example.com/channel/{channel_id}
api.example.com/member/{member_id}
    

I think this is close to (or exactly) the implications of hypermedia - the client can get the other resources if it wants (as long as I tag them sensibly).

PROS: client can choose to load the subordinates or otherwise, better separation of the objects as REST resources
CONS: further trip required to get the secondary resources

Option 3 - enable recursive retrieves

GET api.example.com/user/{user_id}

Read the User object and include links to lists of the sub-objects i.e.

api.example.com/user/{user_id}/channels
api.example.com/user/{user_id}/members

the /channels call would return a list of channel resources in the form (as above):

api.example.com/channel/{channel_id}
    

PROS: primary resources expose where to go to get the subordinates but not what they are (more RESTful?), no requirement to get the subordinates up front, the subordinate list generators (/channels and /members) provide interfaces (method like) making the response more service like.
CONS: three calls now required to fully populate the object

Option 4 - (re)consider the object design for REST

I am re-using the [existing] application object hierarchy and trying to apply it to REST - or perhaps more directly, provide an API interface to it.

Perhaps the REST object hierarchy should be different, or perhaps the new RESTful thinking is exposing limitations of the existing object design.

Any thoughts on the above welcomed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

从来不烧饼 2024-10-03 13:24:59

没有理由不将这些结合起来。

  • api.example.com/user/{user_id} – 返回用户表示
  • api.example.com/channel/{channel_id} – 返回渠道表示
  • api .example.com/user/{user_id}/channels – 返回频道表示列表
  • api.example.com/user/{user_id}/channel_list – 返回频道 ID 列表(或使用上述链接链接到其完整表示)

如有疑问,请考虑如何向人类用户显示数据而无需考虑“API”:用户需要两个索引页面 ({user_id}/channel_list)和完整视图({user_id}/channels)。

一旦你有了这个,只需支持 JSON 而不是(或除了)HTML 作为表示格式,你就拥有了 REST。

There's no reason not to combine these.

  • api.example.com/user/{user_id} – return a user representation
  • api.example.com/channel/{channel_id} – return a channel representation
  • api.example.com/user/{user_id}/channels – return a list of channel representations
  • api.example.com/user/{user_id}/channel_list – return a list of channel ids (or links to their full representations, using the above links)

When in doubt, think about how you would display the data to a human user without "API" concerns: a user wants both index pages ({user_id}/channel_list) and full views ({user_id}/channels).

Once you have that, just support JSON instead of (or in addition to) HTML as the representation format, and you have REST.

谢绝鈎搭 2024-10-03 13:24:59

我能给出的最好建议是尽量避免将 REST api 视为公开对象。您创建的资源应该支持您需要的用例。如果有必要,您可以为所有三个选项创建资源:

api.example.com/completeuser/{id}
api.example.com/linkeduser/{id}
api.example.com/lightweightuser/{id}

显然我的名字有点愚蠢,但您叫它们什么并不重要。这个想法是,您使用 REST api 以最符合特定使用场景的逻辑方式呈现数据。如果有多个场景,请根据需要创建多个资源。我喜欢将我的资源视为 UI 模型而不是业务实体。

The best advice I can give is to try and avoid thinking about your REST api as exposing your objects. The resources you create should support the use cases you need. If necessary you might create resources for all three options:

api.example.com/completeuser/{id}
api.example.com/linkeduser/{id}
api.example.com/lightweightuser/{id}

Obviously my names are a bit goofy, but it really doesn't matter what you call them. The idea is that you use the REST api to present data in the most logical way for the particular usage scenario. If there are multiple scenarios, create multiple resources, if necessary. I like to think of my resources more like UI models rather than business entities.

吐个泡泡 2024-10-03 13:24:59

我会推荐Restful Obects,它是暴露领域模型的restful的标准

Restful Objects的想法是提供一个标准的、通用的RESTful接口对于域对象模型,使用 JSON 公开其结构的表示,并使用 HTTP GET、POST、PUT 和 DELETE 实现与域对象实例的交互。

根据标准,URI 将类似于:

  • api.example.com/object/user/31
  • api.example.com/object/user/31/properties/username
  • api.example.com/object/user/31/collections /channels
  • api.example.com/object/user/31/collections/members
  • api.example.com/object/user/31/actions/someFunction
  • api.example.com/object/user/31/actions/someFunction/invoke

有也是其他资源

  • api.example.com/services
  • api.example.com/domain-types

该规范定义了一些主要表示形式:

  • 对象(表示任何域对象或服务)
  • 列表(指向其他对象的链接)
  • 属性
  • 收集
  • 操作
  • 操作结果(通常包含对象或列表,或仅包含反馈消息)
  • 以及少量辅助表示,例如家庭和用户

这很有趣,因为您会看到表示是完全自描述的,从而开启了可能性如果需要,将实施通用查看器。

或者,这些表示可以直接由定制应用程序使用。

I would recommend Restful Obects which is standards for exposing domain model's restful

The idea of Restful Objects is to provide a standard, generic RESTful interface for domain object models, exposing representations of their structure using JSON and enabling interactions with domain object instances using HTTP GET, POST, PUT and DELETE.

According to the standard, the URIs will be like:

  • api.example.com/object/user/31
  • api.example.com/object/user/31/properties/username
  • api.example.com/object/user/31/collections/channels
  • api.example.com/object/user/31/collections/members
  • api.example.com/object/user/31/actions/someFunction
  • api.example.com/object/user/31/actions/someFunction/invoke

There are also other resources

  • api.example.com/services
  • api.example.com/domain-types

The specification defines a few primary representations:

  • object (which represents any domain object or service)
  • list (of links to other objects)
  • property
  • collection
  • action
  • action result (typically containing either an object or a list, or just feedback messages)
  • and also a small number of secondary representations such as home, and user

This is interesting as you’ll see that representations are fully self-describing, opening up the possibility of generic viewers to be implemented if required.

Alternatively, the representations can be consumed directly by a bespoke application.

撕心裂肺的伤痛 2024-10-03 13:24:59

以下是我经过数小时的搜索和响应者的输入得出的结论:

如果我有一个实际上是多部分对象的对象,我需要将其视为单个资源。因此,如果我获取该对象,则所有下属都应该在场。为了使资源可缓存,这是必需的。如果我部分加载对象(并提供 ETag 标记),那么其他请求者可能会在期望完整对象时收到部分对象。 结论 - 如果对象可作为资源使用,则应完全填充对象。

关联的对象关系应作为指向其他(主要)资源的链接提供。通过这种方式,可以通过遍历 API 来发现对象。

此外,对主应用程序站点有意义的对象层次结构可能看起来不是您以 RESTful 方式操作所需的内容,但更有可能揭示问题与现有的层次结构。话虽如此,API 可能需要比之前设想的更专门的用例,并且可能需要专门的资源。

希望对某人有帮助

Here's my conclusions from many hours searching and with input from the responders here:

Where I have an object that is effectively a multi-part object, I need to treat that as a single resource. Thus if I GET the object, all the sub-ordinates should be present. This is required in order that the resource is cacheable. If I part load the object (and provide an ETag stamp) then other requestors may receive a partial object when they expected a full one. Conclude - objects should be fully populated if they are being made available as resources.

Associated object relationships should be made available as links to other (primary) resources. In this way the objects are discoverable by traversing the API.

Also, the object hierarchy that made sense for main application site may appear not be what you need to act in RESTful manner, but is more likely revealing problems with the existing hierarchy. Having said this the API may require more specialised use cases than had been previously envisaged, and specialised resources may be required.

Hope that helps someone

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文