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

[Bug]: Attribute-defined schemas containing oneOf/anyOf/allOf are merged with property types, no overwriting of types possible #2290

Open
vuryss opened this issue May 30, 2024 · 1 comment
Labels

Comments

@vuryss
Copy link

vuryss commented May 30, 2024

Version

4.26.1

Description

When trying to overwrite the type of a property with OA\Property attribute - using type or ref successfully replaced the types defined by the php itself. However when using oneOf, anyOf or allOf - those are instead merged with the PHP type definitions and it's impossible to overwrite them from attribute alone. The only way to overwrite them is to define them as schema in the config file and use a ref to point to the new schema. This is because of this line:

if (Generator::UNDEFINED !== $property->type || Generator::UNDEFINED !== $property->ref) {
which covers only type and ref. A very easy fix is to add the above 3 in the check.

Now why I need this? I have the following situation:

readonly class Rule
{
    public function __construct(
        public null|float|bool|int|string $value,
    ) {
    }
}

This generates the following spec:

                    "value": {
                        "nullable": true,
                        "oneOf": [
                            {
                                "type": "string",
                                "nullable": true
                            },
                            {
                                "type": "integer",
                                "nullable": true
                            },
                            {
                                "type": "number",
                                "format": "float",
                                "nullable": true
                            },
                            {
                                "type": "boolean",
                                "nullable": true
                            }
                        ]
                    }

However some validators like thephpleague/openapi-psr7-validator match integers to both type interger and type number which makes the validation of the schema of integer input invalid (it's one of, not any of and it matches 2 schemas).

To overcome this I try overwriting it like this:

        #[OA\Property(anyOf: [
            new OA\Schema(type: 'null'),
            new OA\Schema(type: 'number'),
            new OA\Schema(type: 'boolean'),
            new OA\Schema(type: 'integer'),
            new OA\Schema(type: 'string'),
        ])]
        public null|float|bool|int|string $value,

However this results into this spec:

                    "value": {
                        "nullable": true,
                        "anyOf": [
                            {
                                "type": "null"
                            },
                            {
                                "type": "number"
                            },
                            {
                                "type": "boolean"
                            },
                            {
                                "type": "integer"
                            },
                            {
                                "type": "string"
                            }
                        ],
                        "oneOf": [
                            {
                                "type": "string",
                                "nullable": true
                            },
                            {
                                "type": "integer",
                                "nullable": true
                            },
                            {
                                "type": "number",
                                "format": "float",
                                "nullable": true
                            },
                            {
                                "type": "boolean",
                                "nullable": true
                            }
                        ]
                    }

Even if I use oneOf with less types like this:

        #[OA\Property(oneOf: [
            new OA\Schema(type: 'number'),
            new OA\Schema(type: 'boolean'),
            new OA\Schema(type: 'string', nullable: true),
        ])]
        public null|float|bool|int|string $value,

It merges them like that:

                    "value": {
                        "nullable": true,
                        "oneOf": [
                            {
                                "type": "number"
                            },
                            {
                                "type": "boolean"
                            },
                            {
                                "type": "string",
                                "nullable": true
                            },
                            {
                                "type": "string",
                                "nullable": true
                            },
                            {
                                "type": "integer",
                                "nullable": true
                            },
                            {
                                "type": "number",
                                "format": "float",
                                "nullable": true
                            },
                            {
                                "type": "boolean",
                                "nullable": true
                            }
                        ]
                    }
                }

So I cannot overwrite it with anyOf, oneOf or allOf. The only solution is to define in the config a schema like this:

            schemas:
                RuleValue:
                    anyOf:
                        -   type: string
                            nullable: true
                        -   type: number
                            nullable: true
                        -   type: boolean
                            nullable: true

And reference it like this:

        #[OA\Property(ref: '#/components/schemas/RuleValue')]
        public null|float|bool|int|string $value,

Additional context

No response

@vuryss vuryss added the bug label May 30, 2024
@heiglandreas
Copy link
Contributor

Just today I stumbled over the exact same issue. In my case it was even weirder as parts of the merged schema came from the getters and the setters of the property.

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

No branches or pull requests

2 participants