Skip to content

jsonapi.use_iri_as_id config ignored by Laravel provider #8199

@daenerysIII

Description

@daenerysIII

I had AI make the description hope thats ok

API Platform version(s) affected: v4.3.6

Description

The jsonapi.use_iri_as_id config key (documented here) is not read by the Laravel ApiPlatformProvider. In the Symfony integration, ApiPlatformExtension passes this config value as a constructor argument to JsonApiItemNormalizer, but the Laravel provider has no equivalent logic — the config is silently ignored.

Additionally, JsonApiItemNormalizer is declared final, making it impossible for users to extend and override the ID behavior.

The id field is hardcoded at line 129 of vendor/api-platform/json-api/Serializer/ItemNormalizer.php:

$resourceData = [
'id' => $context['iri'], // always returns full IRI like "/api/books/1"
'type' => $this->getResourceShortName($resourceClass),
];
How to reproduce

Create a fresh Laravel app with api-platform/laravel:^4.3

Add 'jsonapi' => ['use_iri_as_id' => false] to config/api-platform.php

Set up a simple resource (e.g. Book) with an id primary key

Request GET /api/books/1 with Accept: application/vnd.api+json

Observe the response uses the full IRI as id:

{ "data": { "id": "/api/books/1", "type": "Book" } }
Expected with use_iri_as_id: false:

{ "data": { "id": "1", "type": "Book", "links": { "self": "/api/books/1" } } }
Possible Solution

The Laravel ApiPlatformProvider should either:

Read api-platform.jsonapi.use_iri_as_id from config and pass it to JsonApiItemNormalizer (though the constructor currently doesn't accept this parameter), or
Expose a hook/override point so users can customize the ID format without needing to decorate a final class
Additional Context

Working around this currently requires a decorator wrapping JsonApiItemNormalizer (since it's final) that post-processes the normalized output, plus overriding the container binding — this is non-trivial and fragile.

The Symfony ApiPlatformExtension does this by reading $config['jsonapi']['use_iri_as_id'] and adding it as an argument to the normalizer service definition:

$container->getDefinition('api_platform.jsonapi.normalizer.item')
->addArgument($config['jsonapi']['use_iri_as_id']);
The same pattern should be applied to the Laravel provider; alternatively, the provider could push it into $defaultContext or the serializer context.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions