jsonapi
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseUse With django-drf
与django-drf配合使用
This skill focuses on spec compliance. For implementation patterns (ViewSets, Serializers, Filters), use skill together with this one.
django-drf| Skill | Focus |
|---|---|
| What the spec requires (MUST/MUST NOT rules) |
| How to implement it in DRF (code patterns) |
When creating/modifying endpoints, invoke BOTH skills.
本技能专注于规范合规性。若需了解实现模式(ViewSets、Serializers、Filters),请将本技能与技能结合使用。
django-drf| 技能 | 核心关注点 |
|---|---|
| 规范的强制要求(MUST/MUST NOT规则) |
| 如何在DRF中实现(代码模式) |
创建/修改端点时,请同时调用这两个技能。
Before Implementing/Reviewing
实现/审核前准备
ALWAYS validate against the latest spec before creating or modifying endpoints:
在创建或修改端点前,务必依据最新规范进行验证:
Option 1: Context7 MCP (Preferred)
选项1:Context7 MCP(推荐)
If Context7 MCP is available, query the JSON:API spec directly:
mcp_context7_resolve-library-id(query="jsonapi specification")
mcp_context7_query-docs(libraryId="<resolved-id>", query="[specific topic: relationships, errors, etc.]")若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.]")Option 2: WebFetch (Fallback)
选项2:WebFetch(备选)
If Context7 is not available, fetch from the official spec:
WebFetch(url="https://jsonapi.org/format/", prompt="Extract rules for [specific topic]")This ensures compliance with the latest JSON:API version, even after spec updates.
若Context7不可用,可从官方规范获取内容:
WebFetch(url="https://jsonapi.org/format/", prompt="Extract rules for [specific topic]")这能确保即使规范更新,也能遵循最新版本的JSON:API要求。
Critical Rules (NEVER Break)
关键规则(绝对不可违反)
Document Structure
文档结构
- NEVER include both and
datain the same responseerrors - ALWAYS include at least one of: ,
data,errorsmeta - ALWAYS use and
type(string) in resource objectsid - NEVER include when creating resources (server generates it)
id
- 绝对不可在同一响应中同时包含和
dataerrors - 必须至少包含以下一项:、
data、errorsmeta - 资源对象中必须使用和
type(字符串类型)id - 创建资源时绝对不可包含(由服务器生成)
id
Content-Type
内容类型
- ALWAYS use
Content-Type: application/vnd.api+json - ALWAYS use
Accept: application/vnd.api+json - NEVER add parameters to media type without /
extprofile
- 必须使用
Content-Type: application/vnd.api+json - 必须使用
Accept: application/vnd.api+json - 绝对不可在媒体类型中添加未带有/
ext的参数profile
Resource Objects
资源对象
- ALWAYS use string for (even if UUID)
id - ALWAYS use lowercase kebab-case for
type - NEVER put or
idinsidetypeattributes - NEVER include foreign keys in - use
attributesrelationships
- 必须为字符串类型(即使是UUID)
id - 必须使用小写短横线命名法(kebab-case)
type - 绝对不可将或
id放在type内attributes - 绝对不可在中包含外键 - 请使用
attributesrelationships
Relationships
关联关系
- ALWAYS include at least one of: ,
links, ordatameta - ALWAYS use resource linkage format:
{"type": "...", "id": "..."} - NEVER use raw IDs in relationships - always use linkage objects
- 必须至少包含以下一项:、
links或datameta - 必须使用资源关联格式:
{"type": "...", "id": "..."} - 绝对不可在关联关系中使用原始ID - 务必使用关联对象
Error Objects
错误对象
- ALWAYS return errors as array:
{"errors": [...]} - ALWAYS include as string (e.g.,
status, not"400")400 - ALWAYS include for field-specific errors
source.pointer
- 必须以数组形式返回错误:
{"errors": [...]} - 必须为字符串类型(例如:
status,而非"400")400 - 字段相关错误必须包含
source.pointer
HTTP Status Codes (Mandatory)
HTTP状态码(强制要求)
| Operation | Success | Async | Conflict | Not Found | Forbidden | Bad Request |
|---|---|---|---|---|---|---|
| GET | | - | - | | | |
| POST | | | | | | |
| PATCH | | | | | | |
| DELETE | | | - | | | - |
| 操作 | 成功 | 异步 | 冲突 | 未找到 | 禁止访问 | 错误请求 |
|---|---|---|---|---|---|---|
| GET | | - | - | | | |
| POST | | | | | | |
| PATCH | | | | | | |
| DELETE | | | - | | | - |
When to Use Each
各状态码适用场景
| Code | Use When |
|---|---|
| Successful GET, PATCH with response body, DELETE with response |
| POST created resource (MUST include |
| Async operation started (return task reference) |
| Successful DELETE, PATCH with no response body |
| Invalid query params, malformed request, unknown fields |
| Authentication ok but no permission, client-generated ID rejected |
| Resource doesn't exist OR RLS hides it (never reveal which) |
| Duplicate ID, type mismatch, relationship conflict |
| Wrong Content-Type header |
| 状态码 | 适用场景 |
|---|---|
| 成功的GET请求、带响应体的PATCH请求、带响应体的DELETE请求 |
| POST请求创建资源成功(必须包含 |
| 异步操作已启动(返回任务引用) |
| 成功的DELETE请求、无响应体的PATCH请求 |
| 无效的查询参数、格式错误的请求、未知字段 |
| 认证通过但无权限、客户端生成的ID被拒绝 |
| 资源不存在或被RLS隐藏(绝不可泄露具体原因) |
| 重复ID、类型不匹配、关联关系冲突 |
| Content-Type请求头错误 |
Document Structure
文档结构
Success Response (Single)
成功响应(单个资源)
json
{
"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-..."
}
}json
{
"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-..."
}
}Success Response (List)
成功响应(资源列表)
json
{
"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}
}
}json
{
"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}
}
}Error Response
错误响应
json
{
"errors": [
{
"status": "400",
"code": "invalid",
"title": "Invalid attribute",
"detail": "UID must be 12 digits for AWS accounts",
"source": {"pointer": "/data/attributes/uid"}
}
]
}json
{
"errors": [
{
"status": "400",
"code": "invalid",
"title": "Invalid attribute",
"detail": "UID must be 12 digits for AWS accounts",
"source": {"pointer": "/data/attributes/uid"}
}
]
}Query Parameters
查询参数
| Family | Format | Example |
|---|---|---|
| | |
| | |
| Comma-separated, | |
| | |
| Comma-separated paths | |
| 类别 | 格式 | 示例 |
|---|---|---|
| | |
| | |
| 逗号分隔, | |
| | |
| 逗号分隔的路径 | |
Rules
规则
- MUST return for unsupported query parameters
400 - MUST return for unsupported
400pathsinclude - MUST return for unsupported
400fieldssort - MUST NOT include extra fields when is specified
fields[type]
- 对于不支持的查询参数,必须返回
400 - 对于不支持的路径,必须返回
include400 - 对于不支持的字段,必须返回
sort400 - 当指定时,绝对不可包含额外字段
fields[type]
Common Violations (AVOID)
常见违规情况(需避免)
| Violation | Wrong | Correct |
|---|---|---|
| ID as integer | | |
| Type as camelCase | | |
| FK in attributes | | |
| Errors not array | | |
| Status as number | | |
| Data + errors | | Only one or the other |
| Missing pointer | | |
| 违规行为 | 错误示例 | 正确示例 |
|---|---|---|
| ID为整数 | | |
| Type使用驼峰命名 | | |
| 属性中包含外键 | | |
| 错误未以数组形式返回 | | |
| Status为数字 | | |
| 同时包含Data和Errors | | 仅包含其中一项 |
| 缺少source.pointer | | |
Relationship Updates
关联关系更新
To-One Relationship
一对一关联关系
http
PATCH /api/v1/providers/123/relationships/tenant
Content-Type: application/vnd.api+json
{"data": {"type": "tenants", "id": "456"}}To clear:
{"data": null}http
PATCH /api/v1/providers/123/relationships/tenant
Content-Type: application/vnd.api+json
{"data": {"type": "tenants", "id": "456"}}清空关联:
{"data": null}To-Many Relationship
一对多关联关系
| Operation | Method | Body |
|---|---|---|
| Replace all | PATCH | |
| Add members | POST | |
| Remove members | DELETE | |
| 操作 | 请求方法 | 请求体 |
|---|---|---|
| 替换所有关联 | PATCH | |
| 添加成员 | POST | |
| 删除成员 | DELETE | |
Compound Documents (include
)
include复合文档(include
)
includeWhen using :
?include=providerjson
{
"data": {
"type": "scans",
"id": "...",
"relationships": {
"provider": {
"data": {"type": "providers", "id": "prov-123"}
}
}
},
"included": [
{
"type": "providers",
"id": "prov-123",
"attributes": {"alias": "Production"}
}
]
}当使用时:
?include=providerjson
{
"data": {
"type": "scans",
"id": "...",
"relationships": {
"provider": {
"data": {"type": "providers", "id": "prov-123"}
}
}
},
"included": [
{
"type": "providers",
"id": "prov-123",
"attributes": {"alias": "Production"}
}
]
}Rules
规则
- Every included resource MUST be reachable via relationship chain from primary data
- MUST NOT include orphan resources
- MUST NOT duplicate resources (same type+id)
- 每个包含的资源必须能通过主数据的关联链访问到
- 绝对不可包含孤立资源
- 绝对不可重复包含资源(相同type+id)
Spec Reference
规范参考
- Full Specification: https://jsonapi.org/format/
- Implementation: Use skill for DRF-specific patterns
django-drf - Testing: Use skill for test patterns
prowler-test-api
- 完整规范:https://jsonapi.org/format/
- 实现:使用技能获取DRF特定的实现模式
django-drf - 测试:使用技能获取测试模式
prowler-test-api