mcpField
J
jsonapi

jsonapi

github.com/prowler-cloud开发15.1k125 次安装今天更新
代码仓库

关于 jsonapi

jsonapi 是面向 JSON:API 端点开发与审查的编码技能,整理了文档结构、资源、关系、错误、查询参数和 HTTP 状态码规范。

主要功能

  1. 01响应与资源结构规范
  2. 02Content-Type 与标识符要求
  3. 03关系与 include 指引
  4. 04错误格式与状态码
  5. 05查询参数校验规则

适用场景

  1. 01检查端点是否符合 JSON:API
  2. 02设计关系更新请求
  3. 03审查 API 错误与查询处理

MCP 相关

该技能建议使用 Context7 MCP 查询最新的 JSON:API 规范。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/prowler-cloud/prowler --skill jsonapi

安装后在 Claude Code 中输入/jsonapi确认已加载。

详细介绍

与 django-drf 搭配使用

此技能侧重于规范合规性。如需了解实现模式(ViewSet、Serializer、Filter),请将 django-drf 技能与此技能搭配使用。

技能侧重点
jsonapi规范要求什么(MUST/MUST NOT 规则)
django-drf如何在 DRF 中实现(代码模式)

创建或修改端点时,必须同时调用这两项技能。


实现或审查前

创建或修改端点前,始终先根据最新规范进行验证:

选项 1:Context7 MCP(首选)

如果 Context7 MCP 可用,请直接查询 JSON:API 规范:

mcp_context7_resolve-library-id(query="jsonapi specification")
mcp_context7_query-docs(libraryId="<resolved-id>", query="[specific topic: relationships, errors, etc.]")
选项 2:WebFetch(备用)

如果 Context7 不可用,请从官方规范获取内容:

WebFetch(url="https://jsonapi.org/format/", prompt="Extract rules for [specific topic]")

这样可确保符合最新版本的 JSON:API,即使规范更新后也不例外。


关键规则(绝不可违反)

文档结构
  • 绝不可在同一响应中同时包含 data 和 errors
  • 始终至少包含以下之一:data、errors、meta
  • 资源对象中始终使用 type 和 id(字符串)
  • 创建资源时绝不可包含 id(由服务端生成)
Content-Type
  • 始终使用 Content-Type: application/vnd.api+json
  • 始终使用 Accept: application/vnd.api+json
  • 未指定 ext/profile 时,绝不可为媒体类型添加参数
资源对象
  • id 始终使用字符串(即使是 UUID)
  • type 始终使用小写 kebab-case
  • 绝不可将 id 或 type 放在 attributes 中
  • 绝不可在 attributes 中包含外键——请使用 relationships
关系
  • 始终至少包含以下之一:links、data 或 meta
  • 始终使用资源关联格式:{"type": "...", "id": "..."}
  • 绝不可在关系中使用原始 ID——始终使用关联对象
错误对象
  • 始终以数组形式返回错误:{"errors": [...]}
  • 始终将 status 设为字符串(例如 "400",而不是 400)
  • 字段级错误始终包含 source.pointer

HTTP 状态码(必须遵守)

操作成功异步冲突未找到禁止错误请求
GET200--404403400
POST201202409404403400
PATCH200202409404403400
DELETE200/204202-404403-
各状态码的适用场景
状态码使用场景
200 OKGET 成功;PATCH 返回响应正文;DELETE 返回响应
201 CreatedPOST 创建了资源(必须包含 Location 标头)
202 Accepted异步操作已启动(返回任务引用)
204 No ContentDELETE 成功;PATCH 不返回响应正文
400 Bad Request查询参数无效、请求格式错误、存在未知字段
403 Forbidden身份验证通过但无权限;拒绝客户端生成的 ID
404 Not Found资源不存在,或被 RLS 隐藏(绝不透露具体原因)
409 ConflictID 重复、类型不匹配、关系冲突
415 UnsupportedContent-Type 标头错误

文档结构

成功响应(单项)
{
  "data": {
    "type": "providers",
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "attributes": {
      "alias": "Production",
      "connected": true
    },
    "relationships": {
      "tenant": {
        "data": {"type": "tenants", "id": "..."}
      }
    },
    "links": {
      "self": "/api/v1/providers/550e8400-..."
    }
  },
  "links": {
    "self": "/api/v1/providers/550e8400-..."
  }
}
成功响应(列表)
{
  "data": [
    {"type": "providers", "id": "...", "attributes": {...}},
    {"type": "providers", "id": "...", "attributes": {...}}
  ],
  "links": {
    "self": "/api/v1/providers?page[number]=1",
    "first": "/api/v1/providers?page[number]=1",
    "last": "/api/v1/providers?page[number]=5",
    "prev": null,
    "next": "/api/v1/providers?page[number]=2"
  },
  "meta": {
    "pagination": {"count": 100, "pages": 5}
  }
}
错误响应
{
  "errors": [
    {
      "status": "400",
      "code": "invalid",
      "title": "Invalid attribute",
      "detail": "UID must be 12 digits for AWS accounts",
      "source": {"pointer": "/data/attributes/uid"}
    }
  ]
}

查询参数

类别格式示例
pagepage[number]、page[size]?page[number]=2&page[size]=25
filterfilter[field]、filter[field__op]?filter[status]=FAIL
sort以逗号分隔,- 表示降序?sort=-inserted_at,name
fieldsfields[type]?fields[providers]=id,alias
include以逗号分隔的路径?include=provider,scan.task
规则
  • 对不支持的查询参数必须返回 400
  • 对不支持的 include 路径必须返回 400
  • 对不支持的 sort 字段必须返回 400
  • 指定 fields[type] 时绝不可包含额外字段

常见违规(避免)

违规情况错误示例正确示例
ID 使用整数"id": 123"id": "123"
类型使用驼峰命名"type": "providerGroup""type": "provider-groups"
外键放在 attributes 中"tenant_id": "...""relationships": {"tenant": {...}}
errors 不是数组{"error": "..."}{"errors": [{"detail": "..."}]}
status 使用数字"status": 400"status": "400"
同时包含 data 和 errors{"data": ..., "errors": ...}只能包含其中一个
缺少指针{"detail": "Invalid"}{"detail": "...", "source": {"pointer": "..."}}

关系更新

一对一关系
PATCH /api/v1/providers/123/relationships/tenant
Content-Type: application/vnd.api+json

{"data": {"type": "tenants", "id": "456"}}

清除关系:{"data": null}

一对多关系
操作方法请求体
替换全部PATCH{"data": [{...}, {...}]}
添加成员POST{"data": [{...}]}
移除成员DELETE{"data": [{...}]}

复合文档(include)

使用 ?include=provider 时:

{
  "data": {
    "type": "scans",
    "id": "...",
    "relationships": {
      "provider": {
        "data": {"type": "providers", "id": "prov-123"}
      }
    }
  },
  "included": [
    {
      "type": "providers",
      "id": "prov-123",
      "attributes": {"alias": "Production"}
    }
  ]
}
规则
  • 每个包含的资源都必须能通过从主要数据开始的关系链访问
  • 不得包含孤立资源
  • 不得重复资源(相同的 type+id)

规范参考

  • 完整规范:https://jsonapi.org/format/
  • 实现:DRF 特定模式请使用 django-drf skill
  • 测试:测试模式请使用 prowler-test-api skill

评论

支持 Markdown