1

作为 RESTful API 提供的资源的功能发现的一部分,我正在寻找一种方法让服务宣布属性的可接受值。考虑以下示例,其中apple资源具有属性color

GET /apples/17

此请求产生:

{
  "name": "My yummy apple",
  "color": "green"
}

为了让客户了解什么color值是有效的,例如PUT在测试这个苹果的新版本时,我可以想到许多可能的方法。但是我在这里没有找到任何最佳实践。HTTP OPTIONS 动词似乎不适用于这种细粒度的发现。我是否应该只向/apples集合添加一个数组属性:

GET /apples

回复:

{
  ...
  "colorValues": ["red", "green"]
}

有没有更好更常用的方法?

编辑: 刚刚意识到一种可能的方法是为所有“真实”资源的模式添加资源。喜欢的东西会为资源GET /schemas/apple产生 JSON 模式表示。apple来自 json-schema.org 的修改示例:

{
    "id": "http://foo.bar/schema#",
    "$schema": "http://json-schema.org/draft-04/schema#",
    "description": "schema for an apple resource",
    "type": "object",
    ...
    "colorValues": {
        "enum": [ "red", "green" ]
    }
}

不过,我还没有找到任何这样的例子。

4

2 回答 2

1

JSON Hyper-Schema 非常适合这种事情。

GET /apples/17
HTTP/1.1 OK
Content-Type: application/json; profile="/schema/apple"

{
  "id": 17,
  "name": "My yummy apple",
  "color": "green"
}

然后,客户端可以取消对超模式的引用,schema/apple以了解接下来可以遵循哪些链接。

GET /schema/apple
HTTP/1.1 OK
Content-Type: application/schema+json

{
  "id": "http://foo.bar/schema/apple",
  "$schema": "http://json-schema.org/draft-04/hyper-schema#",
  "type": "object",
  "properties": {
    "id": { "type": "string", "readOnly": true },
    "name": { "type": "string" },
    "color": { "enum": ["red", "green"] }
  },
  "required": ["id", "name", "color"],
  "links": [
    { "rel": "self", "href": "/apple/{id}" },
    {
      "rel": "http://foo.bar/relation/edit",
      "href": "/apple/{id}",
      "method": "PUT",
      "schema": { "$ref": "#" }
    }
  ]
}

这是您熟悉的 JSON 模式,但包含一个额外的关键字links,用于描述您可以从此资源中访问的链接。href客户端使用原始 JSON 数据中的值评估URI 模板。因此,在这种情况下,链接评估为...

{
  "rel": "http://foo.bar/relation/edit",
  "href": "/apple/17",
  "method": "PUT",
  "schema": { "$ref": "#" }
}

此链接指示客户端可以向其发出PUT请求,/apple/17并且请求正文应针对位于/schema/apple({ "$ref": "#" }表示此架构) 的架构进行验证。

这为您提供了人类可读和机器可执行的功能描述。机器可执行部分很重要,因为通常可以在不破坏现有客户端的情况下对您的 API 进行更改。

注意:此代码是用 JSON Hyper-Schema Draft-04 编写的。最近有一个新版本draft-05出来了。它做了一些有争议的改变。在这一点上,我仍然推荐draft-04。该规范可以在https://datatracker.ietf.org/doc/html/draft-luff-json-hyper-schema-00找到。

于 2017-01-31T00:58:38.990 回答
0

一种可能的方法是拥有两种资源:applescolours. 您的潜在客户将很容易以轻松的方式获得可用的颜色。那么超媒体呢?有很多标准,您可以创建自己的标准,但最好坚持使用一些广泛使用的标准。

例如,如果您想在HAL之后实现它,获取 apple 将如下所示:

GET /apples/17

{
  "name": "My yummy apple",
  "_links": {
     "self": {
       "href": "/apples/17"
     },
   },
   "colour": {
     "id": "green",
     "href": "/colours/green"
   }
}

那么列出所有颜色呢?像这样:

GET /colours

{
  "_links": {
    "self": {
        "href": "/colours"
    }
  },
  "_embedded": {
    "colours": [
      {
         "_links": {
           "self": {
             "href": "/colours/green"
           }
         },
         "id": "green"
      },
      {
         "_links": {
           "self": {
             "href": "/colours/red"
           }
         },
         "id": "red"
      }
    ]
  }
}

这是设计 API 的现代方式,例如被亚马逊采用

Amazon AppStream Web 服务是使用超文本应用程序语言 (HAL) 的基于资源的 API。HAL 提供了一种将 API 的资源和关系表示为超链接的标准方法。使用 HAL,您可以使用 HTTP 方法(GET、PUT、POST、DELETE)提交请求并在响应中接收有关 API 的信息。应用程序可以使用返回的信息来探索 API 的功能。

编辑:

如果不同的实体允许使用不同的颜色,你可以这样做

GET /apples/17

{
  "name": "My yummy apple",
  "_links": {
     "self": {
       "href": "/apples/17"
     },
     "available_colours": {
       "href": "/apples/17/available_colours"
     }
   },
   "colour": {
     "id": "green",
     "href": "/colours/green"
   },      
   "_embedded": {
     "available_colours": [
       {
         "_links": {
           "self": {
             "href": "/colours/green"
           }
         },
         "id": "green"
       },
       {
         "_links": {
           "self": {
             "href": "/colours/red"
           }
         },
         "id": "red"
       }
    ]
  }
}

如您所见,它的结构非常灵活。

于 2017-01-26T19:01:29.993 回答