Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"@OA\\Items() parent type must be "array" in " #6194

Open
Aerendir opened this issue Mar 1, 2024 · 2 comments
Open

"@OA\\Items() parent type must be "array" in " #6194

Aerendir opened this issue Mar 1, 2024 · 2 comments

Comments

@Aerendir
Copy link
Contributor

Aerendir commented Mar 1, 2024

API Platform version(s) affected: 3.2.* (still present in 3.2.15)

Description

Caused by
 ErrorException: @OA\Items() parent type must be "array" in 

How to reproduce

Create an entity that uses an embeddable.

<?php

declare(strict_types=1);

namespace App\Entity;

use ApiPlatform\Metadata as API;
use App\Entity\Embeddable\TestEmbeddable;

#[API\ApiResource]
class TestResource
{
    private ?TestEmbeddable $testEmbeddable = null;

    public function setTestEmbeddable(?TestEmbeddable $testEmbeddable): self
    {
        $this->testEmbeddable = $testEmbeddable;

        return $this;
    }
}
<?php

declare(strict_types=1);

namespace App\Entity\Embeddable;

class TestEmbeddable
{
    private ?array $testArrayOrNull = null;

    public function getTestArrayOrNull(): ?array
    {
        return $this->testArrayOrNull;
    }

    /**
     * Here, removing the "?" (nullability) makes the error disappear
     */
    private function setTestArrayOrNull(?array $arrayOrNull): void
    {
        $this->testArrayOrNull = $arrayOrNull;
    }
}

Trying to get the documentation in Swagger, causes the error.

The error is triggered in zircote/swagger-php:

https://github.com/zircote/swagger-php/blob/a6d8a93e5daa83d3b959221b0f8f176953d145e9/src/Annotations/Items.php#L53-L56

It expects $parent->type be array while it actually is an array with two values:

Screenshot 2024-03-01 alle 17 53 59

The fact that TestEmbeddable::setTestArrayOrNull() accepts an array or a null value causes $parent->type to have an array with the two possible acceptable values: array and null.

With api-platform/core:3.1.* this error didn't happened.

Possible Solution
I think the problem may be in ApiPlatform\JsonSchema\SchemaFactory, but I'm not able to understand what changed that now causes the error.

Additional Context

The code that adds the nullability is this:

return [...$jsonSchema, ...[
'type' => \is_array($jsonSchema['type'])
? array_merge($jsonSchema['type'], ['null'])
: [$jsonSchema['type'], 'null'],
]];

Is here that $type->type is not === 'array' but is equal to ['array', 'null'] and this breaks zircote/swagger-php.

I don't know if the issue has to be fixed in zircote/swagger-php or here, in api-platform/core.

Digging deeper in this issue, I noticed the add of null is done on purpose (correctly):

d793ffb#diff-32d96682e97b6e04a17576ec737dd6cd19face8782e30713fe1fbf254e9ffaf2R89

d793ffb#diff-32d96682e97b6e04a17576ec737dd6cd19face8782e30713fe1fbf254e9ffaf2R241

The root cause of the issue

Swap nullable for type arrays

In line with JSON Schema, the type keyword can now define multiple types for a schema with an array. This is useful new functionality, but has also made nullable redundant. In order to achieve the goal of letting JSON Schema tools understand OpenAPI, it was decided to remove nullable entirely instead of deprecate it.

# OpenAPI v3.0
type: string
nullable: true
# OpenAPI v3.1
type:
- "string"
- "null" 

This follows the keyword independence concept, where keywords should only add constraints, but adding one more keyword should not remove a constraint. Find and replace should solve this one rather quickly.

Source: https://www.openapis.org/blog/2021/02/16/migrating-from-openapi-3-0-to-3-1-0

I'm not sure how to deal with this, but it seems to me that ApiPlatform generates OpenApi docs for version 3.1, while zircote/swagger-php doesn't still fully support it.

Unsure where (and what) to fix this 🤔

Some usefult links

(Possible) Solution

Use the Swagger UI integrated in ApiPlatform:

The types returned are not precise, but, at least, it works...

@soyuka
Copy link
Member

soyuka commented Mar 15, 2024

type can be an array if we follow the json schema specification, I don't think I can do much here.

@Aerendir
Copy link
Contributor Author

Aerendir commented Mar 15, 2024

Yes, I saw the version 3.1 of the OpenAPI specification: it now allows an array.
The problem is that they changed the type of the field, but this is a breaking change as swagger-php is now broken.

When api-platform used the version 3.0, it was possible to use also nelmio/api-docs-bundle (that, in turn, use swagger-php).

But, as api-platform upgraded to version 3.1 of the OpenAPI specification, passing an array with the two possible types, swagger-php broke.

I see only two possible paths:

  • api-platform should allow to choose the version of the OpenAPI specification (3.0|3.1): this way, the retro-compatibility is maintained
  • swagger-php has to upgrade the code to support also the version 3.1 (there is an open task since the 2020 about this support)

For the future, for sure api-platform should take into account that also a minor version may break existing documentations.

The biggest problem, however, is that it is not possible to document external endpoints with api-platform (not entirely, at least): this is another area where api-platform should improve (see also #6173 (comment)).

One problem, many causes as of what it seems.

In the meantime, I dropped nelmio/api-docs-bundle and gone with SwaggerUI integrated in api-platform, but now I don't have a full nor precise documentation for custom operations (that, unfortunately, cannot be addressed in a clean way using custom processors).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants