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

Json REST资源根据状态返回不同的对象,json,rest,Json,Rest,我正试图定义一个RESTAPI,但有一个需求遇到了问题。 我有一个API用户可以做的动作,这是同一件事,但可以用两种不同的方式来做 例如,假设我的用户使用我的API来更改灯光的强度。我会有一个类似的URL 空气污染指数/光照/强度 用户必须更改强度的一个选项是将强度设置为最大亮度的%,另一个选项是将强度设置为以流明为单位的精确值(有一个检测器),用户可以通过低、中、高的“精度”(它改变达到正确强度所需的时间) 我希望用户能够获得当前强度,这意味着他处于哪种模式,取决于模式、百分比或流明值以及精度

我正试图定义一个RESTAPI,但有一个需求遇到了问题。 我有一个API用户可以做的动作,这是同一件事,但可以用两种不同的方式来做

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

空气污染指数/光照/强度

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

我希望用户能够获得当前强度,这意味着他处于哪种模式,取决于模式、百分比或流明值以及精度

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

{
   "Mode" = "Percent",
   "Percent" = 50.5
}
当我处于“百分比”模式时

当我处于“流明”模式时

如果看起来还可以,我如何告诉用户应该解析哪种类型的“对象”

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


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

具体取决于您的API和用户的需求。对RESTful API的相同GET方法调用应始终返回相同的值:URL中的信息定义的资源表示形式,而不返回其他值。如果您在系统中维护状态,则违反了REST规则。(Edit:正如Gimly所指出的,这一说法并不清楚。系统维护自身内部状态并不违反RESTful设计,特别是当请求使用
PUT
POST
DELETE来更改系统状态时。请求依赖该状态进行retu是违法的注册资源的表示形式,或请求状态更改。每个请求都应该是自包含的。)

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

GET /api/light/intensity
GET /api/light/intensity?f=percent
这样一来,
/api/light/intensity
总是引用相同的资源(默认为“精确”表示法,其中数据最多),查询字符串“过滤”表示法,类似于搜索查询。它删除了一些数据(在本例中,是精确的亮度和精度),以支持以某个最大值的百分比表示的相对表示。或者,您可以将其视为控制输出格式:
GET/foo.json
vs
GET/foo.xml
。资源相同,但表示形式不同

要更新资源,可以按照前面的描述获取对象。您的服务器必须了解不同的格式,但您可以将
放入裸URL,或者再次使用查询参数控制服务器所需的格式,然后使用
而不是
流明
百分比
,使负载更加抽象:

PUT /api/light/intensity
  Payload: {"value": 200, "precision": "high"}

PUT /api/light/intensity?f=percent
  Payload: {"value": 50.5}
这允许您为
light
资源构建API,使
强度
成为资源的一个属性。然后,“百分比”在输出中成为一种方便的表示形式,因此当您返回整个
灯光
资源时,它的内容如下:

"light": {
  "name": "the light",
  "id": 12345,
  "intensity": 200,
  "max-intensity": 400,
...
}
因此API用户可以根据
强度
最大强度
计算当前百分比。(当然,你可以用“百分比”代替“最大强度”,让用户用另一种方式计算,但我觉得提供绝对值和让数学计算相对值更自然

编辑

请参阅Tichodroma的答案,了解更好的处理方法。我留下答案是因为评论中的讨论对我很有用,将来可能对其他人有用。

使用。这允许:

  • 客户端告诉服务器它想要
    获取的资源的表示形式
  • 服务器告诉客户端它返回给客户端的资源的表示形式
  • 客户机告诉服务器它将资源的什么表示放到服务器上
定义两种供应商内容类型:

  • 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
}
服务器从
内容类型
头知道如何解释JSON正文。在本例中,它以“百分比”模式处理请求

如果使用第二种内容类型,客户端和服务器将知道如何将请求/响应解释为“Lumes”模式


编辑:请注意,
GET
PUT
请求使用相同的URL,因为请求是关于相同的资源:光强度。唯一不同的是此资源的表示形式。正确的处理方法是内容类型。

您的方法是对相同的资源使用不同的URL列出光照强度。这不是RESTful。一个资源,一个URL。除非我缺少输入错误,否则URL是相同的:
/api/light/intensity
。表示形式从默认值(“精确”,用OP的术语)更改为相对值(或“百分比”)基于查询字符串。查询参数可以控制不同的筛选器和格式,而不会违反资源本身的规范地址。我是否误解了您的评论?
?f=percent
是URL的一部分。查询字符串参数通常用于
PUT /api/light/intensity/
Content-Type: application/vnd.com.example.light.intensity+percentage

{
   "Percent" = 42.7
}