首页 文章

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

提问于
浏览
65

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

我相信我对关键概念有一个合理的把握,但我很难找到任何解决了对象层次结构和REST的人 .

这是问题......

在[application]业务对象层次结构中,我们有:

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

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

现在,考虑我有一些松散耦合的对象,我可能/可能不会填充,具体取决于应用程序的需要 .

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

Option 1 - fully populate the objects:

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

读取User对象(资源)并返回User对象,其中包含预先加载和编码的所有可能的Channel和Member对象(JSON或XML) .

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

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

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

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

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

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

我认为这接近(或确切地说)超媒体的含义 - 客户端可以获得其他资源(只要我明智地标记它们) .

PROS:客户端可以选择加载下属或其他方式,将对象更好地分离为REST资源
缺点:获得二次资源需要进一步的旅行

Option 3 - enable recursive retrieves

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}

PROS:主要资源暴露了去哪里获得subodinates而不是它们是什么(更多RESTful?),没有要求预先让下属,下级列表生成器(/ channels和/ member)提供接口(类似方法)制作响应更多的服务就像 .
缺点:现在需要三个调用才能完全填充对象

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

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

REST对象层次结构可能不同,或者新的RESTful思想可能暴露了现有对象设计的局限性 .

对上述任何想法表示欢迎 .

非常感谢

保罗

4 回答

  • 9

    我建议Restful Obects这是暴露域模型的宁静的标准

    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

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

    • object(表示任何域对象或服务)

    • list(指向其他对象的链接)

    • property

    • 集合

    • 行动

    • 动作结果(通常包含对象或列表,或仅包含反馈消息)

    • 以及少量次要表示,例如home和user

    这很有趣,因为您会看到表示完全是自描述的,这开启了在需要时实现通用查看器的可能性 .

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

  • 39

    以下是我在几个小时内搜索的结论以及响应者的输入:

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

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

    此外,可能会出现对主应用程序站点有意义的对象层次结构不是你需要以RESTful方式行事,但更有可能揭示现有层次结构的问题 . 说到这一点,API可能需要比以前设想的更专业的用例,并且可能需要专门的资源 .

    希望能帮助别人

  • 6

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

    • api.example.com/user/{user_id} - 返回用户表示

    • api.example.com/channel/{channel_id} - 返回 Channels 表示

    • api.example.com/user/{user_id}/channels - 返回 Channels 表示列表

    • api.example.com/user/{user_id}/channel_list - 使用以上链接返回 Channels ID列表(或指向其完整陈述的链接)

    如有疑问,请考虑如何在没有"API"关注的情况下向人类用户显示数据:用户需要索引页面( {user_id}/channel_list )和完整视图( {user_id}/channels ) .

    一旦你有了,只需支持JSON而不是(或除了)HTML作为表示格式,并且你有REST .

  • 25

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

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

    显然我的名字有点傻,但你称之为无关紧要 . 我们的想法是,您使用REST API以最合理的方式为特定使用场景提供数据 . 如果有多个方案,请根据需要创建多个资源 . 我更喜欢将我的资源视为UI模型而不是业务实体 .

相关问题