jsonapi

安装量: 54
排名: #13643

安装

npx skills add https://github.com/prowler-cloud/prowler --skill jsonapi
Use With django-drf
This skill focuses on
spec compliance
. For
implementation patterns
(ViewSets, Serializers, Filters), use
django-drf
skill together with this one.
Skill
Focus
jsonapi
What the spec requires (MUST/MUST NOT rules)
django-drf
How to implement it in DRF (code patterns)
When creating/modifying endpoints, invoke BOTH skills.
Before Implementing/Reviewing
ALWAYS validate against the latest spec
before creating or modifying endpoints:
Option 1: Context7 MCP (Preferred)
If Context7 MCP is available, query the JSON:API spec directly:
mcp_context7_resolve-library-id(query="jsonapi specification")
mcp_context7_query-docs(libraryId="", query="[specific topic: relationships, errors, etc.]")
Option 2: WebFetch (Fallback)
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.
Critical Rules (NEVER Break)
Document Structure
NEVER include both
data
and
errors
in the same response
ALWAYS include at least one of:
data
,
errors
,
meta
ALWAYS use
type
and
id
(string) in resource objects
NEVER include
id
when creating resources (server generates it)
Content-Type
ALWAYS use
Content-Type: application/vnd.api+json
ALWAYS use
Accept: application/vnd.api+json
NEVER add parameters to media type without
ext
/
profile
Resource Objects
ALWAYS use
string
for
id
(even if UUID)
ALWAYS use
lowercase kebab-case
for
type
NEVER put
id
or
type
inside
attributes
NEVER include foreign keys in
attributes
- use
relationships
Relationships
ALWAYS include at least one of:
links
,
data
, or
meta
ALWAYS use resource linkage format:
{"type": "...", "id": "..."}
NEVER use raw IDs in relationships - always use linkage objects
Error Objects
ALWAYS return errors as array:
{"errors": [...]}
ALWAYS include
status
as
string
(e.g.,
"400"
, not
400
)
ALWAYS include
source.pointer
for field-specific errors
HTTP Status Codes (Mandatory)
Operation
Success
Async
Conflict
Not Found
Forbidden
Bad Request
GET
200
-
-
404
403
400
POST
201
202
409
404
403
400
PATCH
200
202
409
404
403
400
DELETE
200
/
204
202
-
404
403
-
When to Use Each
Code
Use When
200 OK
Successful GET, PATCH with response body, DELETE with response
201 Created
POST created resource (MUST include
Location
header)
202 Accepted
Async operation started (return task reference)
204 No Content
Successful DELETE, PATCH with no response body
400 Bad Request
Invalid query params, malformed request, unknown fields
403 Forbidden
Authentication ok but no permission, client-generated ID rejected
404 Not Found
Resource doesn't exist OR RLS hides it (never reveal which)
409 Conflict
Duplicate ID, type mismatch, relationship conflict
415 Unsupported
Wrong Content-Type header
Document Structure
Success Response (Single)
{
"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)
{
"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
{
"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
page
page[number]
,
page[size]
?page[number]=2&page[size]=25
filter
filter[field]
,
filter[field__op]
?filter[status]=FAIL
sort
Comma-separated,
-
for desc
?sort=-inserted_at,name
fields
fields[type]
?fields[providers]=id,alias
include
Comma-separated paths
?include=provider,scan.task
Rules
MUST return
400
for unsupported query parameters
MUST return
400
for unsupported
include
paths
MUST return
400
for unsupported
sort
fields
MUST NOT include extra fields when
fields[type]
is specified
Common Violations (AVOID)
Violation
Wrong
Correct
ID as integer
"id": 123
"id": "123"
Type as camelCase
"type": "providerGroup"
"type": "provider-groups"
FK in attributes
"tenant_id": "..."
"relationships": {"tenant": {...}}
Errors not array
{"error": "..."}
{"errors": [{"detail": "..."}]}
Status as number
"status": 400
"status": "400"
Data + errors
{"data": ..., "errors": ...}
Only one or the other
Missing pointer
{"detail": "Invalid"}
{"detail": "...", "source": {"pointer": "..."}}
Relationship Updates
To-One Relationship
PATCH /api/v1/providers/123/relationships/tenant
Content-Type
:
application/vnd.api+json
{
"data"
:
{
"type"
:
"tenants"
,
"id"
:
"456"
}
}
To clear:
{"data": null}
To-Many Relationship
Operation
Method
Body
Replace all
PATCH
{"data": [{...}, {...}]}
Add members
POST
{"data": [{...}]}
Remove members
DELETE
{"data": [{...}]}
Compound Documents (
include
)
When using
?include=provider
:
{
"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)
Spec Reference
Full Specification
:
https://jsonapi.org/format/
Implementation
Use
django-drf
skill for DRF-specific patterns
Testing
Use prowler-test-api skill for test patterns
返回排行榜