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

我目前正在为现有的PHP应用程序deviseAPI,并为此调查REST作为一种明智的架构方法。

我相信我对关键概念有合理的把握,但是我正在努力find解决了对象层次结构和REST的人。

这是问题…

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

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

在应用程序本身中,我们使用延迟加载方法根据需要使用这些对象的数组填充User对象。 我相信OO术语这是对象聚合,但我已经看到了各种命名不一致,不关心开始一场关于精确的命名约定的战争。

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

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

选项1 – 完全填充对象:

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

读取用户对象(资源)并返回用户对象,其中包含预先加载和编码的所有可能的通道和成员对象(JSON或XML)。

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

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

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

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

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

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

我认为这与超媒体的影响(或确切地说)很接近 – 客户可以根据需要获得其他资源(只要我明智地标记)。

PROS:客户端可以select加载下属或者更好地分离对象作为REST资源
缺点:需要进一步旅行获得次要资源

选项3 – 启用recursion检索

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

阅读用户对象,并包含指向子对象列表的链接

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

/通道调用将返回表单中的通道资源列表(如上所示):

 api.example.com/channel/{channel_id} 

PROS:主要的资源暴露了从哪里去获取子元素,而不是它们是什么(更RESTful?),没有要求获得下属,下级列表生成器(/通道和/成员)提供接口(方法)响应更多的服务。
缺点:现在需要三个电话来充分填充对象

选项4 – (重新)考虑REST的对象devise

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

也许REST对象的层次结构应该是不同的,也许新的RESTful思想暴露了现有对象devise的局限性。

以上任何想法都欢迎。

非常感谢

保罗

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

  • 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。

我可以给出的最好的build议是尽量避免将REST API暴露给对象。 您创build的资源应该支持您需要的用例。 如有必要,您可以为所有三个选项创build资源:

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

很明显,我的名字有点愚蠢,但是你叫他们真的没关系。 这个想法是,您使用REST API来以最合乎逻辑的方式为特定的使用场景呈现数据。 如果有多个场景,则根据需要创build多个资源。 我喜欢将我的资源更像UI模型而不是商业实体。

我会推荐Restful Obects这是暴露领域模型的宁静的标准

Restful Objects的思想是为域对象模型提供标准的通用RESTful接口,使用JSON公开其结构的表示forms,并使用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

该规范定义了几个主要表示forms:

  • 对象(表示任何域对象或服务)
  • 列表(链接到其他对象)
  • 属性
  • 采集
  • 行动
  • 动作结果(通常包含对象或列表,或者只是反馈消息)
  • 还有less量的次要陈述,如家庭和用户

这很有趣,因为您会发现表示是完全自我描述的,如果需要,可以开放通用观察器的可能性。

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

这里是我从很多小时的search结果和来自响应者的意见的结论:

如果我有一个实际上是一个多部分对象的对象,我需要把它作为一个单一的资源。 因此,如果我获得对象,所有的子坐标应该存在。 为了使资源可caching,这是必需的。 如果我部分加载对象(并提供一个ETag邮票),则其他请求者可能会收到一个部分对象,当他们期望一个完整的。 结论 – 对象应该充分填充,如果它们可以作为资源提供。

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

另外,对于主应用程序站点而言有意义的对象层次结构可能不是您需要以RESTful方式运行的方式,而是更有可能揭示现有层次结构的问题。 话虽如此,API可能需要比以前设想更多的专用用例,并且可能需要专门的资源。

希望能帮助别人