对于RESTful服务 - 客户端如何查找资源属性的有效值?

时间:2017-01-25 16:15:32

标签: rest jsonschema discovery capability

作为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的东西会产生apple资源的JSON Schema表示。来自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" ]
    }
}

虽然我没有找到任何这方面的例子。

2 个答案:

答案 0 :(得分: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,用于描述您可以从此资源中获取的链接。客户端使用原始JSON数据中的值评估href 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。它引起了一些有争议的变化。我现在还在推荐04号草案。该规范可在https://tools.ietf.org/html/draft-luff-json-hyper-schema-00找到。

答案 1 :(得分:0)

可能的方法之一是拥有两种资源:applescolours。您的潜在客户将很容易以一种宁静的方式获得可用的颜色。超媒体怎么样?有 many standards ,您可以创建自己的,但最好坚持使用一些广泛使用的。

例如,如果您想在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

  

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"
       }
    ]
  }
}

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