首页 文章

REST API最佳实践:如何接受参数值列表作为输入[关闭]

提问于
浏览
334

我们正在推出一个新的REST API,我想要一些关于如何格式化输入参数的最佳实践的社区意见:

现在,我们的API非常以JSON为中心(仅返回JSON) . 关于我们是否想要/需要返回XML的争论是一个单独的问题 .

由于我们的API输出是以JSON为中心的,我们一直在走一条路,我们的输入有点以JSON为中心,我一直认为这对某些人来说可能很方便,但总的来说很奇怪 .

例如,要获得一些产品详细信息,我们可以立即提取多个产品:

http://our.api.com/Product?id=["101404","7267261"]

我们应该简化为:

http://our.api.com/Product?id=101404,7267261

或者有JSON输入方便吗?更多的痛苦?

我们可能希望接受这两种风格,但这种灵活性是否会导致更多的混乱和头痛(可维护性,文档等)?

更复杂的情况是我们想要提供更复杂的输入 . 例如,如果我们想在搜索上允许多个过滤器:

http://our.api.com/Search?term=pumas&filters={"productType":["Clothing","Bags"],"color":["Black","Red"]}

我们不一定要将过滤器类型(例如productType和颜色)作为请求名称,如下所示:

http://our.api.com/Search?term=pumas&productType=["Clothing","Bags"]&color=["Black","Red"]

因为我们想要将所有过滤器输入组合在一起 .

最后,这真的很重要吗?可能有很多JSON实用程序,输入类型并不重要 .

我知道我们的JavaScript客户端对API进行AJAX调用可能会欣赏JSON输入以使他们的生活更轻松 .

6 回答

  • 287

    我将支持nategood的答案,因为它已经完成,似乎满足了你的需求 . 虽然,我想添加一个评论来识别多个(1个或多个)资源:

    http://our.api.com/Product/101404,7267261

    In doing so, you:

    通过强制他们将您的响应解释为数组来复杂化客户端,如果我提出以下请求,这对我来说是反直觉的: http://our.api.com/Product/101404

    使用一个API创建冗余API以获取所有产品,使用上面的API获取1个或多个产品 . 由于您不应该为了UX而向用户显示超过1页的详细信息,我相信拥有1个以上的ID将毫无用处并且纯粹用于过滤产品 .

    它可能不是那么有问题,但您要么必须通过返回单个实体(通过验证您的响应是否包含一个或多个实体)或让客户端管理它来自己处理这个问题 .

    Example

    我想订购Amazing的书 . 我确切地知道它是哪本书,我在导航恐怖书时在列表中看到它:

    • 万条惊人的线条,0个惊人的测试

    • The return of the amazing monster

    • 让我们重复一些惊人的代码

    • 结束的惊人开始

    选择第二本书后,我被重定向到详细说明列表中书籍部分的页面:

    --------------------------------------------
    Book #1
    --------------------------------------------
        Title: The return of the amazing monster
        Summary:
        Pages:
        Publisher:
    --------------------------------------------
    

    或者在一个页面中仅提供该书的完整详细信息?

    ---------------------------------
    The return of the amazing monster
    ---------------------------------
    Summary:
    Pages:
    Publisher:
    ---------------------------------
    

    My Opinion

    当获取此资源的详细信息时,我建议在保证unicity时使用路径变量中的ID . 例如,下面的API提供了多种获取特定资源详细信息的方法(假设产品具有唯一ID,并且该产品的规范具有唯一名称,您可以自上而下导航):

    /products/{id}
    /products/{id}/specs/{name}
    

    当你需要超过1个资源时,我会建议从更大的集合中过滤 . 对于同一个例子:

    /products?ids=
    

    当然,这是我的意见,因为它没有强加 .

  • 19

    您可能想查看RFC 6570 . 此URI模板规范显示了url如何包含参数的许多示例 .

  • 182

    First:

    我想你可以做两种方式

    http://our.api.com/Product/<id> :如果你只想要一条记录

    http://our.api.com/Product :如果你想要所有记录

    http://our.api.com/Product/<id1>,<id2> :正如詹姆斯建议的那样可以选择,因为Product标签之后是一个参数

    或者我最喜欢的是:

    您可以使用RestFul WS的 Hypermedia as the engine of application state (HATEOAS)属性并执行调用 http://our.api.com/Product ,该调用应返回 http://our.api.com/Product/<id> 的等效URL并在此之后调用它们 .

    Second

    当您必须对网址调用进行查询时 . 我建议再次使用HATEOAS .

    1)打电话给 http://our.api.com/term/pumas/productType/clothing/color/black

    2)打电话给 http://our.api.com/term/pumas/productType/clothing,bags/color/black,red

    3)(使用HATEOAS)打电话给`http://our.api.com/term/pumas/productType/ - >接收所有服装可能网址的网址 - >打电话给你想要的(衣服和包包) - >收到可能的颜色网址 - >打电话给你想要的

  • 7

    First case:

    正常的产品查找将如下所示

    http://our.api.com/product/1

    所以我认为最佳实践将是你这样做

    http://our.api.com/Product/101404,7267261

    Second Case

    使用查询字符串参数进行搜索 - 这样很好 . 我很想将术语与AND和OR结合使用,而不是使用 [] .

    PS这可能是主观的,所以做你觉得舒服的事情 .

    将数据放入URL的原因是链接可以粘贴在站点上/在用户之间共享 . 如果这不是问题,请务必使用JSON / POST .

    编辑:反思我认为这种方法适合具有复合键的实体,但不适合多个实体的查询 .

  • 7

    将值列表作为URL参数传递的标准方法是重复它们:

    http://our.api.com/Product?id=101404&id=7267261

    最服务器代码会将其解释为值列表,尽管许多都具有单值简化,因此您可能需要查看 .

    定界值也可以 .

    如果您需要将JSON发送到服务器,我不喜欢在URL中看到它(这是一种不同的格式) . 特别是,URL具有大小限制(实际上,如果不是理论上的话) .

    我看到一些RESTful执行复杂查询的方式有两个步骤:

    • POST 您的查询要求,收回一个ID(实质上是创建搜索条件资源)

    • GET 搜索,引用上述ID

    • 可选地在需要时删除查询要求,但请注意它们的要求可供重用 .

  • 0

    退一步

    首先,REST将URI描述为通用唯一ID . 有太多人陷入了URI的结构,哪些URI比其他人更多"restful" . This argument is as ludicrous as saying naming someone "Bob" is better than naming him "Joe" – both names get the job of "identifying a person" done. URI只不过是一个普遍唯一的名称 .

    因此,在REST的眼中,争论 ?id=["101404","7267261"] 是否比 ?id=101404,7267261\Product\101404,7267261 更安静是有点徒劳的 .

    现在,已经说过,很多时候如何构造URI通常可以作为RESTful服务中其他问题的良好指标 . 您的URI和问题中有一些红色标记 .

    建议

    • 同一资源的多个URI和 Content-Location

    我们可能希望接受这两种风格,但这种灵活性是否会导致更多的混乱和头痛(可维护性,文档等)?

    URI标识资源 . 每个资源都应该有 one 规范URI . 这并不意味着您不能将两个URI指向同一个资源,但是有明确定义的方法可以执行此操作 . 如果您决定同时使用JSON和基于列表的格式(或任何其他格式),则需要确定哪些格式是主要的规范URI . 对指向相同"resource"的其他URI的所有响应都应包含Content-Location header .

    坚持使用名称类比,拥有多个URI就像为人们设置昵称 . 这是完全可以接受的,而且通常非常方便,但如果我使用昵称,我仍然可能想知道他们的全名 - 这是指官员的“官方”方式 . 这样当有人用他们的全名“Nichloas Telsa”提到某人时,我知道他们正在谈论我称之为“尼克”的同一个人 .

    • 您的URI中的“搜索”

    更复杂的情况是我们想要提供更复杂的输入 . 例如,如果我们想在搜索中允许多个过滤器...

    我的一般经验法则是,如果您的URI包含动词,则可能表示某些内容已关闭 . URI标识一个资源,但是它们不应该表明我们在HTTP的工作中或在宁静的条件下,我们的"uniform interface" .

    要击败名称类比死,在URI中使用动词就像在想要与他们交互时更改某人的名字一样 . 如果我和鲍勃互动,当我想对他说嗨时,鲍勃的名字不会成为“BobHi” . 同样,当我们想要“搜索”产品时,我们的URI结构不应该从“/ Product / ...”更改为“/ Search / ...” .

    回答您的初步问题

    • 关于 ["101404","7267261"] vs 101404,7267261 :我的建议是为了简单起见,避免使用JSON语法's sake (i.e. don' t要求用户在不必要时进行URL编码 . 这将使您的API更有用 . 更好的是,正如其他人所建议的那样,使用标准的 application/x-www-form-urlencoded 格式,因为它可能是最终用户最熟悉的(例如 ?id[]=101404&id[]=7267261 ) . 它可能不是"pretty",但Pretty URIs并不一定意味着可用的URI . 但是,重申我的初步观点,最终在谈到REST时,它并没有过多地依赖它 .

    • 您的复杂搜索URI示例可以与产品示例完全相同的方式解决 . 我建议再次使用 application/x-www-form-urlencoded 格式,因为它已经是许多人熟悉的标准 . 另外,我建议合并两者 .

    你的URI ......

    /Search?term=pumas&filters={"productType":["Clothing","Bags"],"color":["Black","Red"]}
    

    URI编码后的URI ...

    /Search?term=pumas&filters=%7B%22productType%22%3A%5B%22Clothing%22%2C%22Bags%22%5D%2C%22color%22%3A%5B%22Black%22%2C%22Red%22%5D%7D
    

    可以转化为......

    /Product?term=pumas&productType[]=Clothing&productType[]=Bags&color[]=Black&color[]=Red
    

    除了避免URL编码的要求并使事情看起来更标准之外,它现在使API有点均匀化 . 用户知道如果他们想要检索产品或产品列表(两者都被认为是RESTful术语中的单个"resource"),他们对 /Product/... URI感兴趣 .

相关问题