对于RESTful服务,客户机如何找到资源属性的有效值?

对于RESTful服务,客户机如何找到资源属性的有效值?,rest,jsonschema,discovery,capability,Rest,Jsonschema,Discovery,Capability,作为RESTful API提供的资源的功能发现的一部分,我正在寻找一种方法让服务为属性宣布可接受的值。考虑下面的示例,其中 Apple < /Cord>资源具有属性>代码>颜色< /代码>: GET /apples/17 这一请求产生: { "name": "My yummy apple", "color": "green" } 对于一个客户来说,要理解什么样的颜色值是有效的,例如PUTting一个新版本的苹果,我可以想出很多可能的方法。然而,我在这里没有找到任何最佳实践。HTTP选

作为RESTful API提供的资源的功能发现的一部分,我正在寻找一种方法让服务为属性宣布可接受的值。考虑下面的示例,其中<代码> Apple < /Cord>资源具有属性>代码>颜色< /代码>:

GET /apples/17
这一请求产生:

{
  "name": "My yummy apple",
  "color": "green"
}
对于一个客户来说,要理解什么样的
颜色
值是有效的,例如
PUT
ting一个新版本的苹果,我可以想出很多可能的方法。然而,我在这里没有找到任何最佳实践。HTTP选项动词似乎不适合这种细粒度的发现。我是否应该向
/apples
集合添加一个数组属性:

GET /apples
答复:

{
  ...
  "colorValues": ["red", "green"]
}
有没有更好更常用的方法

编辑: 刚刚意识到一种可能的方法是为所有“真实”资源的模式添加资源。类似于
GET/schemas/apple
的东西,可以为
apple
资源生成JSON模式表示。修改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" ]
    }
}

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

一种可能的方法是使用两种资源:
苹果
颜色
。这将是非常容易为您的潜在客户获得可用的颜色在一个安静的方式。超媒体呢?有,您可以创建自己的,但最好还是坚持使用一些广泛使用的

例如,如果您想实现以下功能,那么获得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服务是一个基于资源的API,它使用 超文本应用语言(HAL)。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"
       }
    ]
  }
}

正如您所看到的,它的结构非常灵活。

JSON Hyper Schema非常适合这种情况

GET /apples/17
-

然后,客户机可以在
schema/apple
上取消对超模式的引用,以了解接下来可以使用哪些链接

GET /schema/apple
-

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

{
  "rel": "http://foo.bar/relation/edit",
  "href": "/apple/17",
  "method": "PUT",
  "schema": { "$ref": "#" }
}
此链接指示客户端可以向
/apple/17
发出
PUT
请求,请求主体应根据
/schema/apple
处的模式进行验证(
{“$ref”:“#”}
表示此模式)

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


注意:此代码是用JSON超模式草稿-04编写的。最近发布了一个新版本草案-05。它做出了一些有争议的改变。目前我仍在推荐草案04。该规范可在。

宝贵的输入中找到-我可以肯定地看到它的用途!但在更一般的意义上(例如,传递一组整数值属性的最大允许值),它在我看来相当乏味?例如,假设总共有5种不同的苹果颜色,但不同的实体允许使用不同的颜色?@MarcusJohansson您好,我已经编辑了答案,并为指定实体添加了一些额外的示例,其中包含
可用的\u颜色
。非常感谢!感谢您在这方面的投入。我认为这种方法抓住了我保持定义和模式非常紧凑的雄心。谢谢你的意见!
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": "#" }
    }
  ]
}
{
  "rel": "http://foo.bar/relation/edit",
  "href": "/apple/17",
  "method": "PUT",
  "schema": { "$ref": "#" }
}