JSON:API: `included` schema is `items: {anyOf: []}` when a relation points to a resource without operations (`NotExposed`)

Fermée
#8,700 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 2 jours

Personne n'a encore pris cette issue.

Évaluation

Difficulté
3/5
Temps estimé
Une demi-journée
Accessibilité débutants
65/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
php, symfony
Domaine
api

Piste de recherche

The empty anyOf comes from JsonApi\JsonSchema\SchemaFactory::buildDefinitionPropertiesSchema(), which skips related classes with false === $hasOperations but still writes anyOf when no reference remains. Reproduce with the two resources in the issue and run bin/console api:openapi:export to inspect Book.jsonapi. Done when included.items is a valid schema (for example {"type": "object"}) or has no empty anyOf, and the exported spec passes validation.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

API Platform version(s) affected

4.4.4

Description

A resource has a relation to another resource whose only operation is NotExposed. The included property of the JSON:API document schema is then:

"included": { "type": "array", "items": { "anyOf": [] } }

JSON Schema requires anyOf to be a non-empty array, so the document is invalid. Spectral (oas3-schema) and code generators reject it.

The cause looks like JsonApi\JsonSchema\SchemaFactory::buildDefinitionPropertiesSchema(). It skips a related class when false === $hasOperations, but it still writes anyOf when no reference remains.

How to reproduce
#[ApiResource(operations: [new NotExposed()])]
final class Author
{
    public function __construct(public int $id = 1, public string $name = 'Frank Herbert') {}
}

#[ApiResource(operations: [new Get(provider: [self::class, 'provide'])])]
final class Book
{
    public function __construct(public int $id = 1, public string $title = 'Dune', public Author $author = new Author()) {}
    public static function provide(): self { return new self(); }
}

The Book.jsonapi schema:

"included": {
  "description": "Related resources requested via the \"include\" query parameter.",
  "type": "array",
  "items": { "anyOf": [] },
  "readOnly": true
}

Expected: when no related class has a schema reference, included.items is {"type": "object"}, or the anyOf key is left out.

Additional Context

Checked on api-platform/core v4.4.4, Symfony 7.4, PHP 8.5, in an empty Symfony app. The code of JsonApi\JsonSchema\SchemaFactory on main is the same as in v4.4.4.

The app has only FrameworkBundle, TwigBundle and ApiPlatformBundle, with this config:

$c->extension('api_platform', [
    'mapping' => ['paths' => ['%kernel.project_dir%/src/ApiResource']],
    'formats' => ['jsonapi' => ['application/vnd.api+json']],
    'docs_formats' => ['jsonopenapi' => ['application/vnd.openapi+json']],
    'doctrine' => ['enabled' => false],
]);

The spec comes from bin/console api:openapi:export.

Langage dominant
PHP
Étoiles
2.6k
Forks
988
Merge moyen
4 j 10 h
PR mergées (30 j)
114

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de api-platform/core

Toutes les issues de api-platform/core

Issues similaires

Plus d'issues PHP

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.