Skip to content

Skolem format used even if the resource has an identifier #5451

Description

@fynch

API Platform version(s) affected: 3.0, 3.1

Description

When using a DTO as output, the @id in JSON-LD is using the skolem format even thought the base entity has an identifier and a Get() operation.

How to reproduce

Create a resource with an identifier and a GET operation:

<?php

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;

#[ApiResource(
        operations: [
                new Get(
                        output:   KeyOutput::class,
                        provider: KeyOutputProvider::class
                ),
        ],
)]
class Key {

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column()]
    private int $id;

    public function getId(): int
    {
        return $this->id;
    }
}

Create the DTO:

<?php


class KeyOutput
{
    public int $îd;
}

Create the provider for this DTO :

<?php

class KeyOutputProvider implements ProviderInterface
{

    public function __construct(private readonly KeyRepository $keyRepository)
    {
    }

    public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
    {
        $key =  $this->keyRepository->find($uriVariables['id']);

        $output = new KeyOutput();
        $output->îd = $object->getId();

        return $output;
    }
}

Then GET /api/keys/{id}, the resource provide this output:


{
  "@context": {
    "@vocab": "http://symfony.local.wip/api/docs.jsonld#",
    "hydra": "http://www.w3.org/ns/hydra/core#",
    "îd": "KeyOutput/îd"
  },
  "@type": "KeyOutput",
  "@id": "/api/.well-known/genid/749b06c9b92e0a2fcee4",
  "îd": 1
}

The desired output would be like in 2.6:


{
  "@context": {
    "@vocab": "http://symfony.local.wip/api/docs.jsonld#",
    "hydra": "http://www.w3.org/ns/hydra/core#",
    "îd": "KeyOutput/îd"
  },
  "@type": "Key",
  "@id": "/api/keys/1",
  "îd": 1
}

Possible Solution

There's a genid parameter in ApiProperty that could help with this if I understand the issue correctly
mentioned here: #5046 (comment)
but I wasn't able to make it work, either on the id attribute or the method getId(), and i'm not sure if this is the answer i'm searching for.
The documention doesn't mention this parameter yet and i'm a little lost on what could be wrong here.

Additional Context

This is an issue when working with IRI in operations like POST/PUT because the IRI /api/keys/1 never exists.
If I have a relation with my Key entity, say a Lock entity OneToOne, I want to be able to POST this:

POST /api/locks/1 
body: 
{
 "key": "/api/keys/1"
}

But the result of this is "The input data is misformatted.", like the issue here: #5101

Any help would be appreciated, thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions