zircote / swagger-php

A php swagger annotation and parsing library
http://zircote.github.io/swagger-php/
Apache License 2.0
5.03k stars 933 forks source link

Type required for anyOf defined property. #1593

Closed bobvandevijver closed 2 months ago

bobvandevijver commented 2 months ago

Consider the following promoted property:

public function __construct(
    #[Property(description: 'The parent reservation, if any. Will be false to break loops.',
      anyOf: [
        new Schema(ref: new Model(type: self::class)),
        new Schema(type: 'false'),
        new Schema(type: 'null'),
      ]
    )]
    public self|false|null $parent){}

If I do not add type: 'object' to the attribute, the property will be excluded from the generated OpenAPI JSON. If I do add it, I get the following, with the incorrect type:

                    "parent": {
                        "description": "The parent reservation, if any. Will be false to break loops.",
                        "type": "object",
                        "anyOf": [
                            {
                                "$ref": "#/components/schemas/EquipmentReservation"
                            },
                            {
                                "type": "false"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    }

Did I miss something, or is this indeed incorrect behaviour of the bundle?

DerManoMann commented 2 months ago

Might be the bundle. Given this file, say, any_of.php

<?php

use OpenApi\Attributes as OA;

#[OA\Schema()]
class Model
{
    public function __construct(
        #[OA\Property(description: 'The parent reservation, if any. Will be false to break loops.',
            anyOf: [
                new OA\Schema(ref: Model::class),
                new OA\Schema(type: 'false'),
                new OA\Schema(type: 'null'),
            ]
        )]
        public self|false|null $parent)
    {
    }
}

#[OA\Info(title: "My First API", version: "0.1")]
class ApiController
{
    #[OA\Get(path: '/api/data.json')]
    #[OA\Response(response: '200', description: 'The data')]
    public function status()
    {}
}

using swagger-php directly things do seem to work:

./bin/openapi -b scratch/any_of.php scratch/any_of.php 

yaml:

openapi: 3.0.0
info:
  title: 'My First API'
  version: '0.1'
paths:
  /api/data.json:
    get:
      operationId: 2dccaad985e4999fe394cb99b1781248
      responses:
        '200':
          description: 'The data'
components:
  schemas:
    Model:
      properties:
        parent:
          description: 'The parent reservation, if any. Will be false to break loops.'
          nullable: true
          anyOf:
            -
              $ref: '#/components/schemas/Model'
            -
              type: 'false'
            -
              type: 'null'
      type: object
bobvandevijver commented 2 months ago

You are absolutely right, I've dug in a bit deeper and it seems to be caused by the JMS type not being set, resulting in the property to be removed from the result. Will open a ticket at the bundle instead!