stetodd / jsonapi-bundle
JSON:API request mapping and response serialisation for Symfony, built on league/fractal
Package info
github.com/stetodd/jsonapi-bundle
Type:symfony-bundle
pkg:composer/stetodd/jsonapi-bundle
Requires
- php: >=8.4
- league/fractal: ^0.20.1
- symfony/config: ^7.2|^8.0
- symfony/dependency-injection: ^7.2|^8.0
- symfony/event-dispatcher: ^7.2|^8.0
- symfony/http-foundation: ^7.2|^8.0
- symfony/http-kernel: ^7.2|^8.0
- symfony/routing: ^7.2|^8.0
- symfony/serializer: ^7.2|^8.0
- symfony/string: ^7.2|^8.0
- symfony/translation-contracts: ^3.0
- symfony/validator: ^7.2|^8.0
Suggests
- doctrine/persistence: Allows transformer resolution to unwrap Doctrine entity proxies
This package is auto-updated.
Last update: 2026-06-12 17:17:50 UTC
README
JSON:API request mapping and response serialisation for Symfony, built on league/fractal.
Install
composer require stetodd/jsonapi-bundle
Register in config/bundles.php:
Stetodd\JsonApiBundle\StetoddJsonApiBundle::class => ['all' => true],
Configure in config/packages/stetodd_json_api.yaml:
stetodd_json_api: base_url: 'https://api.example.com' # recursion_limit: 4 # relationship_routes: # self: 'api_{type}_relationship_{relationship}_self' # related: 'api_{type}_relationship_{relationship}_related'
Responses
Inject Stetodd\JsonApiBundle\Response\JsonApiResponder into controllers:
return $this->responder->item($palette); return $this->responder->collection(Palette::class, $palettes, $pagedResult);
Resources implement Contract\IdentifiableResourceInterface (getId(): \Stringable|string). Each resource gets a transformer extending League\Fractal\TransformerAbstract and implementing Contract\ResourceTransformerInterface; transformers are auto-registered via autoconfiguration — no tagging needed.
Paginated collections take any Contract\PagedResultInterface. The ?include= query parameter is honoured per request; a fresh Fractal manager is built per response, so no include state leaks between requests (worker-mode safe).
Requests
Map JSON:API payloads onto DTOs with controller argument attributes:
public function create( #[MapAttributePayload(resourceType: Palette::class)] CreatePaletteAttributesRequest $attributes, ): JsonResponse {
Attribute DTOs implement Request\AttributesDTOInterface (use AttributesDTOTrait), relationship DTOs implement Request\RelationshipsDTOInterface. When a controller maps both, they are bound together through Request\Context / ContextBindingInterface (use ContextBindingTrait). Payloads are validated with symfony/validator; failures return 422 with violation messages.