REST资源根据状态返回不同的对象

时间:2014-07-30 14:27:11

标签: json rest

我正在尝试定义REST API,但我遇到了一个问题。 我有一个API用户可以执行的操作是相同的,但可以通过两种不同的方式完成。

例如,假设我的用户使用我的API来改变灯光的强度。我将有一个类似

的URL

API /光/强度

用户必须更改强度的一个选项是设置为最大亮度的%,另一个选项是将强度设置为精确值,以流明(有一个检测器)并且他可以通过“精确度”可以是低,中,高(它会改变达到正确强度所需的时间)。

我希望用户能够获得当前的强度,这意味着他在哪种模式下,取决于模式,%或流明的值和精度。

这是我丢失的地方,我的GET将返回一个JSON对象,例如,发送类似

的内容是否可以
{
   "Mode" = "Percent",
   "Percent" = 50.5
}

当我处于“百分比”模式和

{
   "Mode" = "Exact",
   "Lumens" = 200,
   "Precision" = "High"
}

当我处于“流明”模式时?

如果这似乎没问题,我该如何告诉用户他应该解析哪种类型的“对象”?

让用户发送更改的最佳方法是什么?我在考虑有两个URL,每个模式一个,比如 PUT / api /光/强度/精确和PUT / api /光/强度/百分比

两者都在等待与上面类似的JSON对象,没有模式。

2 个答案:

答案 0 :(得分:8)

使用HTTP Content negotiation。这允许:

  • 客户端告诉服务器它想要的资源表示为什么GET
  • 服务器告诉客户端它返回给客户端的资源的表示形式,
  • 客户端告诉服务器资源的代表是PUT服务器。

定义两种供应商内容类型:

  • application/vnd.com.example.light.intensity.percentage+json
  • application/vnd.com.example.light.intensity.lumens+json

客户端告诉服务器它想要哪一个:

GET /api/light/intensity/
Accept: application/vnd.com.example.light.intensity+percentage

服务器响应:

200 OK
Content-Type: application/vnd.com.example.light.intensity+percentage

{
   "Percent" = 50.5
}

客户希望改变强度:

PUT /api/light/intensity/
Content-Type: application/vnd.com.example.light.intensity+percentage

{
   "Percent" = 42.7
}

服务器从Content-Type标头知道如何解释JSON主体。在此示例中,它以“百分比”模式处理请求。

如果使用了第二种内容类型,客户端和服务器就会知道在“Lumes”模式下解释请求/响应。

修改:请注意GETPUT请求使用相同的网址,因为请求的资源大致相同:光照强度。所有不同的是此资源的表示。处理此问题的正确方法是内容类型。

答案 1 :(得分:-1)

具体细节取决于您的API以及用户的需求。对RESTful API的相同GET方法调用应始终返回相同的值:由URL中的信息定义的资源表示,而不是其他任何内容。 如果你在系统中保持状态,你就违反了REST的规则。编辑:正如Gimly指出的那样,这个陈述不清楚。它不是一个违反RESTful设计以保持系统自身的内部状态,尤其是当请求使用PUTPOSTDELETE更改系统状态时。这违反了请求依赖该状态返回资源的表示,或请求状态更改。每个请求应该是自包含的。)

我使用查询字符串来更改表示的格式:

GET /api/light/intensity
GET /api/light/intensity?f=percent

那样/api/light/intensity始终引用相同的资源(默认为“精确”表示,其具有最多数据),并且查询字符串“过滤”表示,类似于搜索查询。它删除了一些数据(在这种情况下,确切的亮度和精度),有利于相对表示,以某个最大值的百分比表示。或者,您可以将其视为控制输出格式:GET /foo.json vs GET /foo.xml。资源相同,但表示不同。

要更新资源,您可以按照自己的描述获取对象。您的服务器必须了解不同的格式,但您可以PUT到裸URL,或者再次使用查询参数来控制服务器所期望的格式,然后使用{使您的有效负载更抽象{1}}代替valuelumens

percentage

这允许您以PUT /api/light/intensity Payload: {"value": 200, "precision": "high"} PUT /api/light/intensity?f=percent Payload: {"value": 50.5} 是资源的一个属性的方式构建light资源的API。 “百分比”然后成为输出中的便利表示,因此当您返回整个intensity资源时,它将读取如下内容:

light

因此API用户可以根据"light": { "name": "the light", "id": 12345, "intensity": 200, "max-intensity": 400, ... } intensity计算当前百分比。 (当然,您可以将“百分比”替换为“最大强度”并让用户以其他方式进行数学运算,但我觉得提供绝对值并让数学计算相对值更自然。

修改

请参阅Tichodroma的答案,以便更好地处理此问题。我要留下答案,因为评论中的讨论对我很有用,将来可能对其他人有用。