后端API设计【免费下载链接】json-apiA specification for building JSON APIs项目地址https://gitcode.com/gh_mirrors/js/json-api点击查看免费下载导读本文围绕 examples/index.md 中提供的官方实战示例系统讲解 JSON:API 规范1.1中三个最常用的进阶特性Sparse Fieldsets稀疏字段集、分页链接Pagination Links与错误对象Error Objects。这些特性分别对应客户端按需取字段、翻页遍历数据、优雅上报错误三类高频需求是构建可维护 API 的必备技能。读完本文你将掌握fields[TYPE]参数的精确用法与易错点、四种标准分页链接的返回规则以及错误对象全部成员的语义与多种典型错误响应写法并能结合仓库内的规范原文与 JSON Schema 测试用例验证每一种写法。一、Sparse Fieldsets按类型精确裁剪响应字段Sparse Fieldsets 允许客户端**按资源类型per-type**要求服务端只返回指定字段从而显著降低响应体积、节省带宽。其语法核心是fields[TYPE]查询参数。1.1 基础用法请求与完整响应基础请求不带任何字段裁剪服务端返回资源全量字段GET /articles?includeauthor HTTP/1.1HTTP/1.1 200 OK Content-Type: application/vnd.apijson { data: [{ type: articles, id: 1, attributes: { title: JSON:API paints my bikeshed!, body: The shortest article. Ever., created: 2015-05-22T14:56:29.000Z, updated: 2015-05-22T14:56:28.000Z }, relationships: { author: { data: {id: 42, type: people} } } }], included: [ { type: people, id: 42, attributes: { name: John, age: 80, gender: male } } ] }1.2 带fields[TYPE]参数的请求客户端声明articles对象只保留title、body、author三个字段people对象只保留name字段GET /articles?includeauthorfields[articles]title,body,authorfields[people]name HTTP/1.1响应随之裁剪HTTP/1.1 200 OK Content-Type: application/vnd.apijson { data: [{ type: articles, id: 1, attributes: { title: JSON:API paints my bikeshed!, body: The shortest article. Ever. }, relationships: { author: { data: {id: 42, type: people} } } }], included: [ { type: people, id: 42, attributes: { name: John } } ] }注意articles中的created、updated与people中的age、gender已从响应中消失。1.3 关键易错点relationship 也是字段Sparse Fieldsets 的一个高频坑关系relationship名称同样属于字段。官方示例特别强调当fields[articles]只写title,body而遗漏author时——即使请求中带有?includeauthor——响应中articles的relationships也会被一并剔除GET /articles?includeauthorfields[articles]title,bodyfields[people]name HTTP/1.1HTTP/1.1 200 OK Content-Type: application/vnd.apijson { data: [{ type: articles, id: 1, attributes: { title: JSON:API paints my bikeshed!, body: The shortest article. Ever. } }], included: [ { type: people, id: 42, attributes: { name: John } } ] }此时relationships.author整块消失。因此凡是需要保留关系的场景必须把关系名同时写进include和fields。1.4 规范原文依据上述行为并非随意设计规范 fetching-sparse-fieldsets 小节约 L1314-L1343有明确约束fields[TYPE]的取值必须是逗号U002C分隔的字段名列表空值表示不返回任何字段一旦客户端为某类型指定了字段子集响应中该类型的资源对象禁止出现额外字段若客户端未指定某类型的字段集服务端可以返回全部、部分或零个字段该规则适用于以资源为主数据或 included 数据的任何端点与请求方法无关——例如POST创建资源的请求同样可以配合稀疏字段集使用。此外查询参数中的方括号[]在规范附录 Square Brackets in Parameter NamesL2218-L2228中有专门说明示例 URI 中未编码的方括号仅为可读性展示实际请求中应进行百分号编码服务端应当同时接受未编码方括号的请求并将其视为与已编码请求等价。二、分页链接用标准 links 对象遍历大数据集JSON:API 本身不限定具体分页策略页码/游标均可但要求分页链接必须使用标准化的键名并放置在与集合对应的links对象中。2.1 完整示例基于页码page-based的策略假设每页 1 条、当前请求第 3 页GET /articles?page[number]3page[size]1 HTTP/1.1HTTP/1.1 200 OK Content-Type: application/vnd.apijson { meta: { totalPages: 13 }, data: [ { type: articles, id: 3, attributes: { title: JSON:API paints my bikeshed!, body: The shortest article. Ever., created: 2015-05-22T14:56:29.000Z, updated: 2015-05-22T14:56:28.000Z } } ], links: { self: http://example.com/articles?page[number]3page[size]1, first: http://example.com/articles?page[number]1page[size]1, prev: http://example.com/articles?page[number]2page[size]1, next: http://example.com/articles?page[number]4page[size]1, last: http://example.com/articles?page[number]13page[size]1 } }这里links中携带了self、first、prev、next、last五个链接客户端无需自行拼接页码即可顺序遍历。2.2 分页链接的四条标准键根据规范 fetching-pagination 小节约 L1400-L1437分页链接必须使用以下键名键含义first第一页数据last最后一页数据prev上一页数据next下一页数据同时需遵守分页链接必须出现在集合对应的links对象中主数据的翻页放顶层links复合文档compound document中 included 集合的翻页则放在该集合对应的 links 对象里某链接不可用时该键必须省略或置为null不能用其他占位写法链接所表达的顺序语义必须与 JSON:API 的排序规则sorting保持一致page查询参数族被规范保留用于分页服务端与客户端应当SHOULD使用它。规范明确对分页策略保持中立页码策略可用page[number]page[size]游标策略可用page[cursor]仓库中另有 Cursor Pagination profile 定义了page[size]、page[before]、page[after]三个参数并解释了其对 offset–limit 缺点的规避。2.3 关于meta.totalPages的两点提示把totalPages放进meta是一种向客户端传递总页数的便捷方式last链接只给出最后一页的 URI本身并不表达总页数但meta中所有值都是实现相关的字段名可自由选择total、count均可也可以完全不用。同样地示例 URI 中的未编码方括号仅为可读性展示实际传输时应百分号编码参见上文 1.4 节引用的规范附录。三、错误对象Error Objects结构化的错误上报错误对象用于在操作失败时向客户端提供结构化诊断信息。规范要求错误对象必须以errors数组的形式出现在 JSON:API 文档顶层见 error-objects 小节约 L2146-L2183并且必须包含至少一个成员其余成员均可选。3.1 基础错误对象下面示例中服务端在创建/更新资源时发现firstName属性非法HTTP/1.1 422 Unprocessable Entity Content-Type: application/vnd.apijson { errors: [ { status: 422, source: { pointer: /data/attributes/firstName }, title: Invalid Attribute, detail: First name must contain at least two characters. } ] }各成员语义source通过 RFC 6901 JSON Pointer 指出请求文档中导致错误的具体位置title问题的通用简要描述正常情况下不随具体发生场景变化可本地化detail针对本次发生实例的人类可读说明比title更具体status与该问题关联的 HTTP 状态码字符串形式。当一次返回多个错误时尤为有用——HTTP 响应本身只能有一个状态码对单个错误也有价值可省去客户端翻查响应头的开销还便于未来 JSON:API 在非 HTTP 协议上使用。3.2 一次请求、多个错误单个请求触发多个错误时将每个错误依次加入errors数组即可HTTP/1.1 400 Bad Request Content-Type: application/vnd.apijson { errors: [ { status: 403, source: { pointer: /data/attributes/secretPowers }, detail: Editing secret powers is not authorized on Sundays. }, { status: 422, source: { pointer: /data/attributes/volume }, detail: Volume does not, in fact, go to 11. }, { status: 500, source: { pointer: /data/attributes/reputation }, title: The backend responded with an error, detail: Reputation service not responding after three requests. } ] }规范对错误对象的唯一唯一性约束是id字段——同一个属性上的多个错误可以各自拥有独立的错误对象。例如firstName同时违反两条规则HTTP/1.1 422 Unprocessable Entity Content-Type: application/vnd.apijson { errors: [ { source: { pointer: /data/attributes/firstName }, title: Invalid Attribute, detail: First name must contain at least two characters. }, { source: { pointer: /data/attributes/firstName }, title: Invalid Attribute, detail: First name must contain an emoji. } ] }注对于上面返回 422 的响应使用400 Bad Request也是可接受的。JSON:API 规范对 400 与 422 的选择不持立场服务端可自由决定。3.3 错误码code与jsonapi顶层成员code是应用自定义的错误码字符串用于标识问题类型。它与title类似都描述某类问题区别于detail针对具体实例但code更适合程序化处理——因为同一title在不同语言本地化后可能呈现不同文本而code保持稳定。假设 API 文档定义了如下码表CodeProblem123Value too short225Password lacks a letter, number, or punctuation character226Passwords do not match227Password cannot be one of last five passwords携带错误码的多错误响应HTTP/1.1 422 Unprocessable Entity Content-Type: application/vnd.apijson { jsonapi: { version: 1.1 }, errors: [ { code: 123, source: { pointer: /data/attributes/firstName }, title: Value is too short, detail: First name must contain at least two characters. }, { code: 225, source: { pointer: /data/attributes/password }, title: Passwords must contain a letter, number, and punctuation character., detail: The password provided is missing a punctuation character. }, { code: 226, source: { pointer: /data/attributes/password }, title: Password and password confirmation do not match. } ] }此例有两点值得注意响应同时包含errors与jsonapi两个顶层成员。规范规定错误响应不能包含顶层data成员但可以包含 JSON:API 定义的其他所有顶层成员第三个错误对象故意省略了detail可能出于安全考虑再次印证错误对象所有成员均可选。3.4source进阶用法指向文档顶层、请求头与查询参数场景一请求文档缺少data成员。客户端发送了非法文档PATCH /posts/1 HTTP/1.1 Content-Type: application/vnd.apijson Accept: application/vnd.apijson { datum: [ ] }服务端用source.pointer指向文档顶层空字符串来定位问题HTTP/1.1 422 Unprocesssable Entity Content-Type: application/vnd.apijson { errors: [ { source: { pointer: }, detail: Missing data Member at documents top level. } ] }Pointer 语义细节指向表示文档顶层若要指向请求文档{: some value}中的字符串值应使用/而/data在此处非法因为请求文档在/data处并无值——source.pointer始终相对于请求文档解析。场景二请求根本不是合法 JSON。此时文档不存在、source无从指起应直接返回解析错误{ errors: [{ status: 400, detail: JSON parse error - Expecting property name at line 1 column 2 (char 1). }] }场景三问题源于 URI 查询参数。使用source.parameter指明出错的参数名GET /api/posts/1?includeauthor HTTP/1.1HTTP/1.1 400 Bad Request Content-Type: application/vnd.apijson { errors: [ { source: { parameter: include }, title: Invalid Query Parameter, detail: The resource does not have an author relationship path. } ] }规范error-objects为source定义了三种取值pointer指向请求文档中的具体值、parameter指明引发错误的 URI 查询参数名、header指明引发错误的单个请求头名称三者取其一或省略。3.5 查询参数错误处理的宽严之别规范在大多数情况下要求遇到 JSON:API已定义查询参数的非法取值时服务端必须返回错误。但对于 API自定义非 JSON:API 定义的查询参数服务端可以选择忽略非法参数并让请求成功而不是报错。关键约束自定义查询参数的名称必须包含至少一个非 a-z 字符。规范 Implementation-Specific Query Parameters约 L2114-L2124还建议用大写字母如 camelCase来满足该要求以保证自定义参数与规范内建参数名不冲突。典型非法参数示例?fields[people]—— 参数名非法正确写法是fields[people]?redirect_tohttp%3A%2F%2Fwww.owasp.org—— 非法参数此例实为钓鱼攻击向量。四、源码与测试佐证仓库为上述特性提供了双重证据链规范原文所有行为均可在 _format/1.1/index.md 中找到对应章节——Sparse Fieldsets 见 fetching-sparse-fieldsetsL1314 起、分页见 fetching-paginationL1400 起、错误对象见 error-objectsL2146 起可验证的 JSON Schema 测试用例仓库_schemas/1.0/tests/目录收录了大量正反例例如 one_error.json 展示了一个包含id、links.about、status、code、title、source.pointer全部成员的错误对象合法样例_schemas/1.0/tests/response/invalid/下还有 error_must_be_an_object.json、invalid_error_objects.json 等反例可用来校验自己的错误响应是否符合规范。分页策略补充规范本身对策略中立若需更现代的游标分页可研读仓库中的 Cursor Pagination profile它定义了page[size]、page[before]、page[after]三个查询参数并论述了游标式分页相对 offset–limit 在删除/新增导致的翻页错位与大数据集性能上的优势可作为页码式之外的第二种实战选型。五、实战要点速查特性核心参数/成员关键注意点Sparse Fieldsetsfields[TYPE]a,b,c关系名也是字段须同时出现在include与fields值为空串表示不返回任何字段分页链接links:first/last/prev/next不可用时键须省略或置nullpage参数族专用于分页错误对象errors数组id/links/status/code/title/detail/source/meta必须含至少一个成员错误响应不得含顶层datastatus为字符串source三选一pointer/parameter/header编码规范[]实际请求中应对方括号做百分号编码服务端应兼容未编码形式延伸阅读规范 1.1 全文见 _format/1.1/index.md更多规格化错误/分页相关测试用例见 _schemas/1.0/tests/若想了解扩展机制profiles如何在此基础上叠加能力可浏览 extensions/index.md。赞分享后端API设计【免费下载链接】json-apiA specification for building JSON APIs项目地址https://gitcode.com/gh_mirrors/js/json-api点击查看免费下载相关推荐LoopmacOS 窗口管理的免费开源指南LoopmacOS 窗口管理的免费开源指南 Loop 是一款免费开源的 macOS 窗口管理工具。按住一个触发键朝某个方向移动鼠标窗口就自动摆到对应位置—桌面应用JSON:API 规范示例详解字段过滤、分页与错误处理JSON:API 规范示例详解字段过滤、分页与错误处理 前言 JSON:API 是一种用于构建高效 RESTful API 的规范它通过标准化的请求和响应格后端API设计Flow 非对称子类型错误修复指南接口、对象类型与类实例error_026_asymmetric_subtyping 实战解析Flow 非对称子类型错误修复指南接口、对象类型与类实例error_026_asymmetric_subtyping 实战解析 在 Flow 的静态类型系开发工具静态分析代码质量上一篇SQL 注入测试不用背 Payload用 CyberStrikeAI 从一句指令到漏洞报告下一篇Qlib Alpha158 量化因子指南一篇跑通每日打分的因子预测基线创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
