[Bug]: Attribute-defined schemas containing oneOf/anyOf/allOf are merged with property types, no overwriting of types possible
Opened this issue · 1 comments
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:
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
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.