文档API设计教程【免费下载链接】api-blueprintAPI Blueprint项目地址https://gitcode.com/gh_mirrors/ap/api-blueprint点击查看免费下载API Blueprint 是一套建立在 Markdown 语义之上的 Web API 描述语言而超媒体Hypermedia则要求 API 响应本身携带下一步能做什么的导航信息。本文以仓库中的 examples/Polls Hypermedia API.md 为完整范本逐段拆解如何用 API Blueprint 描述一个同时以Sirenapplication/vnd.sirenjson与HALapplication/haljson两种媒体类型输出、具备超媒体控件的投票 API。读完本文你将掌握元数据节、URI 模板与参数节、Relation 关系节、多响应事务示例等 API Blueprint 核心语法的实战用法并能独立编写一份可被解析器、模拟服务器与文档工具直接消费的超媒体 API 蓝图。一、为什么需要超媒体版蓝图从 Polls API 到 Polls Hypermedia API仓库的examples/目录下同时存在两个同源但设计取向不同的示例examples/Polls API.md —— 传统数据驱动版本。响应体直接给出url字段如url: /questions/1并通过 HTTPLink头如Link: /questions?page2; relnext传递分页关系文档还明确建议客户端跟随url链接值或Link/Location头而不是自行拼接 URL。examples/Polls Hypermedia API.md —— 超媒体版本。同样的资源改用Siren与HAL两种媒体类型表达用links、actions、entities、_links、_embedded等标准结构把可执行的操作直接内嵌进响应体。两份文档都使用FORMAT: 1A与HOST: http://polls.apiblueprint.org/开头。根据 API Blueprint Specification.md 的定义FORMAT、HOST属于元数据节Metadata section以键: 值形式写在文档最开头键值对按行分隔遇到第一个非键值对的 Markdown 元素即结束。FORMAT: 1A声明蓝图遵循 Format 1A本仓库规范版本为 revision 9HOST则给出模拟/测试时的基准地址。对比两份文档可以清晰看到超媒体并不是新增 API 资源而是同一资源的表达方式升级。因此一份优秀的超媒体蓝图往往同时写出多种媒体类型的响应示例这正是本文范本的核心价值。二、入口点资源用超媒体引导客户端Polls Hypermedia API 的第一个资源是入口点Entry PointURI 模板为/# Polls API Root [/] This resource does not have any attributes. Instead it offers the initial API affordances. ## Retrieve the Entry Point [GET] Response 200 (application/vnd.sirenjson) { links: [ { rel: [ questions ], href: /questions } ] } Response 200 (application/haljson) { _links: { questions: { href: /questions } } }语法要点资源节Resource section由方括号内的 URI 模板 定义形如# 标识符 [URI 模板]。这里的标识符是Polls API Root。动作节Action section由## 标识符 [HTTP 方法]定义这里是Retrieve the Entry Point [GET]。双响应示例同一个GET动作下挂了两个 Response 200分别标注媒体类型application/vnd.sirenjson与application/haljson。依据规范中 Response section 的说明响应节定义应当包含 HTTP 状态码作为标识符并可选携带媒体类型。Siren 与 HAL 对入口点的建模高度一致入口点资源没有业务属性只提供questions链接指向/questions——客户端不需要硬编码任何业务 URL跟随链接即可进入资源图。Siren 用links数组 relHAL 用_links对象 相对链接键二者语义等价。三、Questions CollectionURI 模板、参数节与列表响应## Questions Collection [/questions{?page}] Parameters page: 1 (optional, number) - The page of questions to return3.1 URI 模板中的查询参数资源 URI 模板[/questions{?page}]使用了 RFC 6570 的form-style query 操作符?。规范附录 URI Templates 指出API Blueprint 使用 RFC 6570 子集{?var}展开为?varvalue{var}用于追加查询项如?pathtest{vartwo}展开为?pathtestvartwohello。3.2 参数节语法 Parameters是 URI parameters section其子项遵循固定格式 参数名: 示例值 (类型, required | optional) - 描述本示例中page: 1 (optional, number)表示参数名为page示例值1类型number可选optional若省略required | optional修饰符默认按required处理省略类型时默认string。还可通过 Default:给出默认值、 Members给出枚举值枚举时应把类型写为enum[type]。参数节应只描述父级 URI 模板中出现的参数。3.3 List All Questions [GET]Siren 完整响应### List All Questions [GET] Relation: questions Response 200 (application/vnd.sirenjson) { actions: [ { name: add, href: /questions, method: POST, type: application/json, fields: [ { name: question }, { name: choices } ] } ], links: [ { rel: [ next ], href: /questions?page2 }, { rel: [ self ], href: /questions } ], entities: [ { actions: [ { name: delete, href: /questions/1, method: DELETE } ], rel: [ question ], properties: { published_at: 2014-11-11T08:40:51.620Z, question: Favourite programming language? }, links: [ { rel: [ self ], href: /questions/1 } ], entities: [ { actions: [ { name: vote, href: /questions/1/choices/1, method: POST } ], rel: [ choice ], properties: { choice: Swift, votes: 2048 }, links: [ { rel: [ self ], href: /questions/1/choices/1 } ] }, { actions: [ { name: vote, href: /questions/1/choices/2, method: POST } ], rel: [ choice ], properties: { choice: Python, votes: 1024 }, links: [ { rel: [ self ], href: /questions/1/choices/2 } ] }, { actions: [ { name: vote, href: /questions/1/choices/3, method: POST } ], rel: [ choice ], properties: { choice: Objective-C, votes: 512 }, links: [ { rel: [ self ], href: /questions/1/choices/3 } ] }, { actions: [ { name: vote, href: /questions/1/choices/4, method: POST } ], rel: [ choice ], properties: { choice: Ruby, votes: 256 }, links: [ { rel: [ self ], href: /questions/1/choices/4 } ] } ] } ] }这个响应是超媒体设计的典型示范三层嵌套清晰可见集合级actions声明添加问题能力name: addmethod: POST含fields表单定义集合级links提供next分页与self导航entities中的每个问题rel: question自带delete动作、self链接以及内嵌的choice实体列表每个选项rel: choice又自带vote动作与self链接。3.4 同一响应的 HAL 表达 Response 200 (application/haljson) { _links: { self: { href: /questions }, next: { href: /questions?page2 } }, _embedded: { question: [ { _links: { self: { self: /questions/1 } }, _embedded: { choice: [ { _links: { self: { self: /questions/1/choices/1 } }, choice: Swift, votes: 2048 }, { _links: { self: { self: /questions/1/choices/2 } }, choice: Python, votes: 1024 }, { _links: { self: { self: /questions/1/choices/3 } }, choice: Objective-C, votes: 512 }, { _links: { self: { self: /questions/1/choices/4 } }, choice: Ruby, votes: 256 } ] }, question: Favourite programming language?, published_at: 2014-11-11T08:40:51.620Z } ] } }HAL 用_links承载导航、_embedded承载内嵌资源与 Siren 的links/entities一一对应。在同一个动作下并列写出两种媒体类型的响应正是 API Blueprint 多事务示例multiple transaction examples能力的体现——规范在 Action section 中说明一个动作可以包含多个请求/响应分组每个分组代表一个完整事务示例且同组内多个请求/响应应使用不同标识符这里靠媒体类型区分。3.5 Create a New Question [POST]请求体 双媒体响应### Create a New Question [POST] You may create your own question using this action. It takes a JSON object containing a question and a collection of answers in the form of choices. question (string) - The question choices (array[string]) - A collection of choices. Relation: create Request (application/json) { question: Favourite programming language?, choices: [ Swift, Python, Objective-C, Ruby ] } Response 201 (application/vnd.sirenjson) { actions: [ { name: delete, href: /questions/1, method: DELETE } ], properties: { published_at: 2014-11-11T08:40:51.620Z, question: Favourite programming language? }, links: [ { rel: [ self ], href: /questions/1 } ], entities: [ { actions: [ { name: vote, href: /questions/1/choices/1, method: POST } ], rel: [ choices ], properties: { choice: Swift, votes: 2048 }, links: [ { rel: [ self ], href: /questions/1/choices/1 } ] }, { actions: [ { name: vote, href: /questions/1/choices/2, method: POST } ], rel: [ choices ], properties: { choice: Python, votes: 1024 }, links: [ { rel: [ self ], href: /questions/1/choices/2 } ] }, { actions: [ { name: vote, href: /questions/1/choices/3, method: POST } ], rel: [ choices ], properties: { choice: Objective-C, votes: 512 }, links: [ { rel: [ self ], href: /questions/1/choices/3 } ] }, { actions: [ { name: vote, href: /questions/1/choices/4, method: POST } ], rel: [ choices ], properties: { choice: Ruby, votes: 256 }, links: [ { rel: [ self ], href: /questions/1/choices/4 } ] } ] } Response 201 (application/haljson) { _links: { self: { href: /questions/1 } }, _embedded: { choices: [ { _links: { self: { self: /questions/1/choices/1 } }, choice: Swift, votes: 2048 }, { _links: { self: { self: /questions/1/choices/2 } }, choice: Python, votes: 1024 }, { _links: { self: { self: /questions/1/choices/3 } }, choice: Objective-C, votes: 512 }, { _links: { self: { self: /questions/1/choices/4 } }, choice: Ruby, votes: 256 } ] }, published_at: 2014-11-11T08:40:51.620Z, question: Favourite programming language? }请求侧体现了 Request section 的用法 Request (application/json)携带媒体类型紧接的缩进代码块即请求体。值得注意 question (string)、 choices (array[string])这两个列表项写在动作描述与Relation之间用于简要声明请求字段及其类型与 Advanced Tutorial.md 中用 MSON 的 Attributes描述请求结构的思路互补本示例直接用内联字段声明未引入完整 MSON 类型定义。响应侧则展示了一个语义细节201 Created在 Siren 中以rel: [ choices ]内嵌选项、在 HAL 中以_embedded.choices表达二者都向客户端宣告新资源已可用且可以立即投票。四、Group Question 资源组与 Question 资源详情# Group Question Resources related to questions in the API. ## Question [/questions/{question_id}] A Question object has the following attributes: question published_at - An ISO8601 date when the question was published. url choices - An array of Choice objects. Parameters question_id: 1 (required, number) - ID of the Question in form of an integer4.1 资源组# Group Question是 Resource group section由Group关键字 标识符定义用于将相关资源组织在一起可嵌套一个或多个资源节。这里的描述Resources related to questions in the API与普通版 Polls API 完全一致。4.2 资源属性Attributes 的简化写法 question、 published_at、 url、 choices这组列表项以属性名 说明的形式声明 Question 对象的字段published_at标注为 ISO8601 日期choices标注为 Choice 对象数组。规范中 Attributes section 指出资源节的属性代表资源数据结构若资源带名称这些属性可被其他Attributes节按名称引用完整 MSON 语法可进一步给出类型、默认值与必填性参见 Attributes (object)及 Data Structures 节。4.3 路径参数 question_idURI 模板/questions/{question_id}使用路径段变量RFC 6570 Level 1 展开形式配合参数节声明question_id为required, number。注意参数名的写法——大括号内的变量名question_id与参数节列表项的名称必须一致。规范还允许在动作级覆盖参数资源级参数对所有嵌套动作生效除非动作自身定义了 URI 模板。4.4 View a Questions Detail [GET] 与双媒体响应### View a Questions Detail [GET] Relation: question Response 200 (application/vnd.sirenjson) { actions: [ { name: delete, href: /questions/1, method: DELETE } ], properties: { published_at: 2014-11-11T08:40:51.620Z, question: Favourite programming language? }, links: [ { rel: [ self ], href: /questions/1 } ], entities: [ { actions: [ { name: vote, href: /questions/1/choices/1, method: POST } ], rel: [ choices ], properties: { choice: Swift, votes: 2048 }, links: [ { rel: [ self ], href: /questions/1/choices/1 } ] }, { actions: [ { name: vote, href: /questions/1/choices/2, method: POST } ], rel: [ choices ], properties: { choice: Python, votes: 1024 }, links: [ { rel: [ self ], href: /questions/1/choices/2 } ] }, { actions: [ { name: vote, href: /questions/1/choices/3, method: POST } ], rel: [ choices ], properties: { choice: Objective-C, votes: 512 }, links: [ { rel: [ self ], href: /questions/1/choices/3 } ] }, { actions: [ { name: vote, href: /questions/1/choices/4, method: POST } ], rel: [ choices ], properties: { choice: Ruby, votes: 256 }, links: [ { rel: [ self ], href: /questions/1/choices/4 } ] } ] } Response 200 (application/haljson) { _links: { self: { href: /questions/1 } }, _embedded: { choices: [ { _links: { self: { self: /questions/1/choices/1 } }, choice: Swift, votes: 2048 }, { _links: { self: { self: /questions/1/choices/2 } }, choice: Python, votes: 1024 }, { _links: { self: { self: /questions/1/choices/3 } }, choice: Objective-C, votes: 512 }, { _links: { self: { self: /questions/1/choices/4 } }, choice: Ruby, votes: 256 } ] }, published_at: 2014-11-11T08:40:51.620Z, question: Favourite programming language? } Relation: question声明该动作的链接关系类型link relation type。依据规范 Relation section 与 Advanced Tutorial.md 的Relation Types章节 Relation: 标识符为动作赋予领域语义使客户端可以基于语义而非具体 URI构建——例如无论资源路径如何变化查看问题始终是question关系。规范同时提醒同一蓝图内每个资源的 relation 标识符应保持唯一。五、Choice 资源嵌套参数与投票动作## Choice [/questions/{question_id}/choices/{choice_id}] Parameters question_id: 1 (required, number) - ID of the Question in form of an integer choice_id: 1 (required, number) - ID of the Choice in form of an integer5.1 双路径参数URI 模板同时包含两个路径段变量参数节依次声明question_id与choice_id均为required, number。规范附录指出变量名仅允许字母、数字、_、百分号编码字符与.且多个变量必须以逗号分隔、不得含空格。5.2 View a Choice Detail [GET]### View a Choice Detail [GET] Relation: choice Response 200 (application/vnd.sirenjson) { actions: [ { name: vote, href: /questions/1/choices/1, method: POST } ], rel: [ choice ], properties: { choice: Swift, votes: 2048 }, links: [ { rel: [ self ], href: /questions/1/choices/1 } ] } Response 200 (application/haljson) { _links: { self: { href: /questions/1/choices/1 } }, choice: Swift, votes: 2048 }单个选项的资源表示非常精简Siren 版本携带vote动作与self链接HAL 版本只保留_links与业务字段。这说明超媒体蓝图同样尊重资源越小越清晰的 REST 实践。5.3 Vote on a Choice [POST]展示状态变迁### Vote on a Choice [POST] This action allows you to vote on a questions choice. Relation: vote Response 201 (application/vnd.sirenjson) { actions: [ { name: vote, href: /questions/1/choices/1, method: POST } ], rel: [ choice ], properties: { choice: Swift, votes: 2049 }, links: [ { rel: [ self ], href: /questions/1/choices/1 } ] } Response 201 (application/haljson) { _links: { self: /questions/1/choices/1 }, choice: Swift, votes: 2049 }对比上文 GET 的响应体可以看到投票后votes从2048变为2049——蓝图用相邻两个事务示例精确刻画了状态变迁。这正是 API Blueprint 文档即测试特性的价值解析器/测试工具可以直接用这两个示例校验真实 API 的行为是否符合预期参见 examples/README.md 对examples 目录中所有文件均为有效蓝图的说明。六、与普通版 Polls API 的关键差异速查维度Polls API非超媒体Polls Hypermedia API媒体类型application/jsonapplication/vnd.sirenjson、application/haljson导航方式响应体url字段 Link头links/_linksrel关系可执行操作客户端自行拼接 URLSirenactions含method、fields/ HAL 链接内嵌资源普通 JSON 嵌套对象Sirenentities/ HAL_embedded语义关系无显式关系声明每个动作带 Relation:声明创建响应201Location头201 完整超媒体实体含投票动作普通版的Retrieve the Entry Point返回{questions_url: /questions}超媒体版则分别用 Sirenlinks与 HAL_links表达同一导航意图。两者共享相同的资源集合、Question 属性模型与 Choice 参数定义——区别只在于链接与动作如何呈现。七、如何验证与消费这份蓝图阅读源码本仓库中 examples/Polls Hypermedia API.md 本身就是一份可解析的FORMAT: 1A文档由于以.md命名GitHub 会自动渲染见 examples/README.md建议以 raw 方式查看原稿。对照规范逐节语法可对照 API Blueprint Specification.md文档结构总览见其Blueprint document structure小节进阶概念Relation、Attributes、Data Structures可参考 Advanced Tutorial.md 与 Tutorial.md。生成文档与模拟API Blueprint 生态工具如 Apiary、各类开源解析器与模拟服务器可直接消费此类蓝图基于HOST元数据生成模拟端点 Relation:声明与双媒体类型响应可被客户端代码生成器与测试工具如 Dredd识别。约定与限制以本仓库为准蓝图遵循 Format 1Arevision 9媒体类型通过(application/...)标注在 Request/Response 定义行同一动作下不同响应靠不同媒体类型形成独立事务示例。参数默认required、类型默认string查询参数需用{?var}或{var}形式写入 URI 模板。八、结语Polls Hypermedia API 示范了一条可复用的路线资源模型保持不变仅通过媒体类型选择与 Relation 声明把 API 从URL 手册升级为可导航的超媒体应用。在 API Blueprint 中这一切只需要在响应示例中忠实写出 Siren/HAL 结构并为每个动作加上 Relation:即可——蓝图既是人类可读的 Markdown 文档又是机器可解析、可模拟、可测试的 API 契约。赞分享文档API设计教程【免费下载链接】api-blueprintAPI Blueprint项目地址https://gitcode.com/gh_mirrors/ap/api-blueprint点击查看免费下载相关推荐Simple Live一站式跨平台直播聚合应用使用指南Simple Live一站式跨平台直播聚合应用使用指南 你是否厌倦了在多个直播应用之间来回切换想要一个统一的平台来观看所有主流直播内容Simple Liv音视频直播球面卷积神经网络终极指南如何在3D球形数据上构建等变深度学习模型球面卷积神经网络终极指南如何在3D球形数据上构建等变深度学习模型 球面卷积神经网络S2CNN是处理球形数据和3D旋转等变信号的前沿深度学习框架。这个开源项API Blueprint实战Polls API从规范到代码全流程API Blueprint实战Polls API从规范到代码全流程 你是否还在为API设计与开发的脱节而烦恼是否经历过文档与实际接口不一致的尴尬本文将通过文档API设计教程上一篇开源项目Mini QR本地部署教程Docker与Nginx配置实现私有化部署下一篇OpenJarvis 挖矿子系统扩展指南基于 Provider 合约与 Sidecar 机制接入 Pearl 挖矿创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考