RESTAPI子资源,要返回的数据?

RESTAPI子资源,要返回的数据?,rest,restful-architecture,restful-url,api-design,Rest,Restful Architecture,Restful Url,Api Design,如果我们有客户和订单,我正在寻找获取此数据的正确RESTful方法: { "customer": { "id": 123, "name": "Jim Bloggs" "orders": [ { "id": 123, "item": "Union Jack Keyring", "qty": 1 }, { "id": 987, "item": "London Eye T

如果我们有
客户
订单
,我正在寻找获取此数据的正确RESTful方法:

{
  "customer": {
    "id": 123,
    "name": "Jim Bloggs"
    "orders": [
      {
        "id": 123,
        "item": "Union Jack Keyring",
        "qty": 1
      }, {
        "id": 987,
        "item": "London Eye Ticket",
        "qty": 5
      }
    ]
  }
}
  • GET/customers/123/订单
  • GET/customers/123?inc orders=1
  • URL的最后一部分/文件夹(不包括查询字符串参数)应该是返回的资源,对吗

    如果是这样,编号1应仅返回订单数据,而不包括客户数据。数字2直接指向customer
    123
    ,并使用查询字符串参数影响/过滤返回的客户数据,在本例中包括订单数据


    这两个调用中哪一个是上述JSON的正确RESTful调用。。。还是有一个秘密数字3选项?

    您发布的JSON看起来像是

    GET /customers/123
    
    前提是客户资源包含订单集合作为属性;或者,您可以嵌入它们,或者提供指向它们的链接

    后者将导致如下结果:

    GET /customers/123/orders
    
    这将返回类似于

    {
        "orders": [
          {
            "id": 123,
            "item": "Union Jack Keyring",
            "qty": 1
          }, 
          {
            "id": 987,
            "item": "London Eye Ticket",
            "qty": 5
          }
        ]
    }
    

    你有3个选择,我认为可以被认为是宁静的

    (一)
    GET/customers/12
    但一定要包括订单。您是否有客户不想使用订单的情况?或者订单数组会变得非常大吗?如果是这样,你可能需要另一个选择

    (二)
    GET/customers/123
    ,其中可能包含指向其订单的链接,如下所示:

    {
      "customer": {
        "id": 123,
        "name": "Jim Bloggs"
        "orders": {
           "href": "<link to you orders go here>"
        }
      }
    }
    
    {
    “客户”:{
    “id”:123,
    “姓名”:“吉姆·布洛格斯”
    “命令”:{
    “href”:”
    }
    }
    }
    
    有了这个,你的客户必须提出两个请求才能得到客户和他们的订单。这种方式的好处是,您可以轻松地对订单实现干净的分页和过滤

    (三)
    GET/customers/123?字段=订单
    这类似于第二种方法。这将允许客户端更有效地使用您的API,但除非您真的需要限制从服务器返回的字段,否则我不会走这条路。否则,它将给您的API增加不必要的复杂性,您将不得不对其进行维护

    我正在寻找获取这些数据的正确RESTful方法

    只需在指向生成此数据的资源的URI上执行HTTP
    GET
    请求

    TL;DR

    • REST并不关心URI设计,而是关注它的约束
    • 客户端通过服务器通过响应中包含的动态标识的超链接返回的可能操作执行状态转换
    • 客户端和服务器可以协商首选的超媒体类型
    • <> LI>而不是嵌入整个(子)资源,只考虑将链接返回到该资源,以便客户端可以在感兴趣的查找它。

    首先,REST并不真正关心URI设计,只要URI是唯一的。当然,简单的URI设计对人类来说更容易理解,尽管与HTML相比,实际链接可以隐藏在更有意义的文本后面,因此对人类来说也不是那么重要,只要他们能够找到链接并对其执行操作。接下来,为什么您认为您的“响应”或API是RESTful的?要调用API RESTful,API应该考虑以下几个方面。在这些限制中有一个相当流行的词:作为应用程序状态引擎的超文本(HATEOAS)

    REST是我们每天使用的Web的广义概念。web会话的一个非常常见的任务是,客户机请求一些内容,其中服务器发送一个HTML文档,其中包含大量链接和其他资源,客户机可以使用这些资源来请求进一步的页面或流式传输视频(或其他任何内容)。用户在客户端上的操作可以使用返回的信息继续进行,请求新页面,向服务器发送信息等等。RESTful应用程序也是如此。这就是REST简单地定义为HATEOAS。如果您现在查看您的“响应”,并仔细检查HATEOAS约束,您可能会发现您的响应不包含任何开始的链接。因此,客户需要领域知识才能继续

    JSON本身并不是最好的超媒体类型,因为它只定义了数据的整体语法,但没有任何语义,类似于纯XML,虽然它可能有一些DTD或模式,但客户端可以使用这些DTD或模式来验证文档,并检查其他地方是否有进一步的语义规则。有两种基于JSON的超媒体类型可能更适合f.e(在本文中可以找到基于JSON的超媒体类型的良好比较)。当然,您有权定义自己的超媒体类型,尽管某些客户可能无法理解它

    如果你看一下f.e.,你会发现它定义了一个
    \u嵌入的
    元素,你可以在其中放入某些子资源。这对你来说似乎很理想。根据您的设计,
    orders
    本身也可以是一种资源,因此可以通过
    GET/orders/{orderId}
    本身进行访问。除了嵌入整个子资源,您还可以只包含指向该(子)资源的链接,以便客户机可以在感兴趣时查找数据

    如果您只想返回客户数据,而其他情况下还想包含订单数据,您可以为两者定义不同的超媒体类型(基于HAL f.e.),一种仅返回客户数据,另一种还包括订单数据。这些类型可以这样命名:
    application/vnd.yourcompanyname.version.customers.hal+json
    application/vnd.yourcompanyname.version.customer\u orders.hal+json
    。与向请求中添加简单的查询参数相比,这无疑是一种开发开销,但语义更清晰,文档开销在超媒体类型(或表示)上,而不是在HTT上
    GET GET /customers/123/
    Accept: application/vnd.acme.customer.short+json
    
    200 OK
    Content-Type: application/vnd.acm.customer.short+json
    
    {
      "customer": {
        "id": 123,
        "name": "Jim Bloggs"
      }
    }
    
    GET GET /customers/123/
    Accept: application/vnd.acme.customer.full+json
    
    200 OK
    Content-Type: application/vnd.acme.customer.full+json
    
    {
      "customer": {
        "id": 123,
        "name": "Jim Bloggs"
        "orders": [
          {
            "id": 123,
            "item": "Union Jack Keyring",
            "qty": 1
          }, {
            "id": 987,
            "item": "London Eye Ticket",
            "qty": 5
          }
        ]
      }
    }