Choose Your Stack
Why JsonApi4j
One standard. Every service. No more API design debates — just consistent, spec-compliant endpoints out of the box.
JSON:API Compliant
Purpose-built around the JSON:API specification — predictable request/response format and processing rules.
Auto-Generated OpenAPI
Always-in-sync API documentation derived from the same metadata used at runtime. Powerful customization capabilities. Exposed as JSON or YAML via a dedicated endpoint.
Framework Agnostic
Works with Spring Boot, Quarkus, and plain Jakarta Servlet API. Add one dependency and the framework auto-configures itself in your environment.
Under the Hood
Built for engineers who care about what happens between the request and the response.
Pluggable Architecture
Hook into the request pipeline with the visitor-based Plugin System. Ships with Access Control, Sparse Fieldsets, OpenAPI, and Compound Documents plugins.
Compound Documents
Multi-level include queries with parallel batch resolution, built-in caching, and Cache-Control aggregation. Deployable at the application or API Gateway level.
Fine-Grained Access Control
Declarative, annotation-driven authorization — per-field anonymization based on access tier, OAuth2 scopes, and resource ownership. No changes to core logic.
Minimal Boilerplate
Define resources, relationships, and operations — the framework automatically generates JSON:API documents, pagination links, error responses, and many more.
Persistence/Data Source Agnostic
No JPA or Hibernate required. Works with SQL, NoSQL, REST clients, in-memory stores, or any data source you bring.
Parallel Execution
Relationship resolution, compound document fetching, and batch operations run concurrently. Supports virtual threads (Project Loom) for maximum throughput.
Request Processing Pipeline
Every incoming API request flows through a well-defined processing pipeline — from data retrieval through relationship resolution to final document composition. At each stage, registered plugins can inspect, mutate, or short-circuit the request using the Visitor pattern.
Quick Example
Define a resource and an operation — that’s all it takes to expose a fully compliant JSON:API endpoint:
@JsonApiResource(resourceType = "users")
public class UserResource implements Resource<UserDbEntity> {
@Override
public String resolveResourceId(UserDbEntity dto) {
return dto.getId();
}
@Override
public UserAttributes resolveAttributes(UserDbEntity dto) {
return new UserAttributes(dto.getFullName(), dto.getEmail());
}
}
@JsonApiResourceOperation(resource = UserResource.class)
public class UserOperations implements ResourceOperations<UserDbEntity> {
@Override
public CursorPageableResponse<UserDbEntity> readPage(JsonApiRequest request) {
return PaginationAwareResponse.limitOffsetAware(
userDb.readAll(request.getLimit(), request.getOffset()),
userDb.total()
);
}
}
GET /users →
{
"data": [
{
"type": "users",
"id": "1",
"attributes": {
"fullName": "John Doe",
"email": "john@example.com"
},
"links": {
"self": "/users/1"
}
}
],
"links": {
"self": "/users?page[offset]=0&page[limit]=20",
"next": "/users?page[offset]=20&page[limit]=20"
}
}