nelmio / NelmioApiDocBundle

Generates documentation for your REST API from annotations
MIT License
2.23k stars 833 forks source link

Multiple types on one Property is acting weird #2138

Open etshy opened 1 year ago

etshy commented 1 year ago

I'm not sure the error concerns this repo or swagger-php bu the error I got comes from nelmio file.

I have a case with an old API where Properties can be integer, string or null I tried making the following

#[OA\Property(anyOf: [new OA\Schema(type: "null"), new OA\Schema(type: 'integer'), new OA\Schema(type: 'string')])]
private $property;

But the spec generation crash with the following error

The PropertyInfo component was not able to guess the type of App\Application\Command\Command::$property. You may need to add a `@var` annotation or use `@OA\Property(type="")` to make its type explicit.

I tried adding @var like this

/**
 * @var string|int|null
 */
#[OA\Property(anyOf: [new OA\Schema(type: "null"), new OA\Schema(type: 'integer'), new OA\Schema(type: 'string')])]
private $property;

It works, but generate both anyOf and oneOf

"Command": {
    "properties": {
        "property": {
            "anyOf": [
                {
                    "type": "null"
                },
                {
                    "type": "integer"
                },
                {
                    "type": "string"
                }
            ],
            "oneOf": [
                {
                    "type": "integer",
                    "nullable": true
                },
                {
                    "type": "string"
                }
            ]
        },
    }
}

and in the doc web page, it only show one type (the first one on the @var docblock)

ps : I also tried using oneOf instead of anyOf, but spec generated looks like this

"Command": {
    "properties": {
        "property": {
            "oneOf": [
                {
                    "type": "null"
                },
                {
                    "type": "integer"
                },
                {
                    "type": "string"
                },
                {
                    "type": "integer",
                    "nullable": true
                },
                {
                    "type": "string"
                }
            ]
        },
    }
}
DjordyKoert commented 11 months ago

I think using the anyOf spec is incorrect here because you are using an union type here.

anyOf – validates the value against any (one or more) of the subschemas

oneOf is the correct on here since this specifies that only one of the schemas is valid.

oneOf – validates the value against exactly one of the subschemas

Also note that null is not a valid schema type.

Note that there is no null type; instead, the nullable attribute is used as a modifier of the base type.

https://swagger.io/docs/specification/data-models/data-types/

DjordyKoert commented 11 months ago

It is still weird that the generated string typed schema is missing the nullable property.

I would have assumed that it would end up like this when only the @var annotation is present:


"Command": {
    "properties": {
        "property": {
            "oneOf": [
                {
                    "type": "integer",
                    "nullable": true
                },
                {
                    "type": "string",
                    "nullable": true
                }
            ]
        },
    }
}