我的 JSON 响应是否应该包含请求查询参数值?

Should my JSON reponse contain the request query parameter's value?

我应该在响应中包含输入查询参数吗?

假设我有一个 return 人名的端点。我允许我的客户按国家过滤结果。

我想知道,我是否应该在响应中包含国家 属性,即使它符合客户的要求。

例如当用户发送以下请求时

/people?country=英国

我应该return

[{"name":"tom"},{"name"="tim"}]

[{"name":"tom","country":"UK"},{"name":"tim","country":"UK"}]

作为回应?

取决于客户需要什么数据。

如果您只是想告诉客户他们请求什么,您可以在 API 中有一些约定,即有一个顶级节点显示请求中的参数是生成此回复。

{"requestParams":"country=UK&city=London", data: [{"name":"tom", "street":"Wallaby"}, {"name":"tim", "street":"West"}]

但您绝对不想冒险通过返回请求参数来返回敏感信息。

为了回答您的问题,我们应该首先澄清 REST 背后的实际意图,因为这经常被误解。 REST 不是关于干净的 URI 或像 APIs 这样的流行语,它是关于将客户端与类似于 Web 浏览器的服务器分离,这些服务器非常健壮并且几乎不会在服务器更改时中断。

为了实现这一点,客户端不应该对 API 或其资源有任何假设或预定义的知识。它需要知道的一切都应该通过请求-响应交互来学习。这并不容易实现,但可以确保在服务器端所做的更改不会破坏客户端。

因此,服务器应包含链接 (HATEOAS),客户端可以使用这些链接在调用这些 URI 时执行状态更改。支持协议(通常是 HTTP)定义了您可以对这些 URI 执行的动词(或方法)。为了避免将客户端耦合到服务器,客户端可以将已知的支持文档格式列表(例如网络浏览器中的 text/html)发送到服务器,并且服务器可以选择一种支持的文档类型和将资源状态转换为这种格式(如果支持)。此内容类型现在定义了 return 发送给客户端的内容。这可能是刚刚转换为相应表示(因此表示状态传输;REST)的资源的完整内容,或者可能只是某些资源状态的子视图。

已经有多种可用的内容类型定义,但 API 提供商可以创建自己的内容类型定义或根据需要从其他定义中扩展。然而,自定义内容类型的缺点是客户需要以某种方式了解这些内容类型。媒体类型虽然是 RESTful 客户的实际知识库,但 Roy Fielding 还表示,大部分设计工作应该放在媒体类型及其处理上:

A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. Any effort spent describing what methods to use on what URIs of interest should be entirely defined within the scope of the processing rules for a media type (and, in most cases, already defined by existing media types). [Failure here implies that out-of-band information is driving interaction instead of hypertext.] (Roy Fielding)

虽然 application/xmlapplication/json 非常流行并得到广泛支持,但它们并没有表达太多语义。 application/atom+xmlapplication/hal+json 之类的东西至少支持支持 HATEOAS 要求的链接。

因此,为了成为真正的 RESTful,您应该为您的 people 信息重新使用 vCard 等现有内容类型,或者设计一些新内容并制作它公开可用,以便客户实现者有办法了解这些内容类型的处理。通用 vcard 内容类型已经定义了您可以 return 的内容,而在自定义内容类型上,您可以随意 return 任何您想要的内容,但至少支持此内容类型的客户端将是能够进一步处理数据。

我只想说你应该选择一个最小的代表你的项目与收集响应一起发送,并在return处理这些时保持一致。

由于查询值始终取决于最终 returning 的项目的基础数据,因此该数据属于您 return 对它们的表示,当个人请求项目 - 即 /people/tom 将包括 {"country:"UK"}。只需决定您要将完整项目的哪些部分包含在列表中。

如果提供的查询过滤的 属性 不是您通常对 "person" 的最小表示形式,则不要包含它。如果它通常是您在调用 /people?foo 时包含的个人数据的一部分,那么仍然包含它。