Skip to content

@ApiProperty() annotation is ignored for objects #3945

Description

@maks-rafalko

API Platform version(s) affected: 2.5.9

Description

@ApiProperty() annotation is ignored for objects

How to reproduce

For a property that has a type of another class, we would like to override OpenAPI documentation by adding @ApiProperty annotation:

/**
 * @ApiProperty(
 *     attributes={
 *         "openapi_context"={
 *             "type"="string",
 *             "enum"=AddressType::ALL,
 *             "example"=AddressType::MAILING
 *         }
 *     }
 * )
 */
private AddressType $addressType;

In OpenAPI documentation request/response example:

Expected Result:

{
  "addressType": "mailing"
}

Actual Result:

{
  "addressType": {}
}

In generate OpenAPI/Swagger document:

Expected Result:

{
  "properties": {
    "addressType": {
      "type": "string",
      "enum": [
        "billing",
        "mailing"
      ],
      "example": "mailing"
    }
  }
}

Actual Result:

{
  "properties": {
    "addressType": {
      "$ref": "#/components/schemas/AddressType-create_address",
      "type": "string",
      "enum": [
        "billing",
        "mailing"
      ],
      "example": "mailing"
    }
  }
}

(!) Note the $ref key added - this is an actual bug, because $ref key takes precedence and all other keys are ignored.

Possible Solution

Solution if to NOT add $ref key for Property Schema when it already has other keys, here:

$propertySchema = new \ArrayObject($propertySchema + $valueSchema);

So, I would suggest the following diff:

- $propertySchema = new \ArrayObject($propertySchema + $valueSchema);
+ if (count($propertySchema) > 0 && array_key_exists('$ref', $valueSchema)) {
+    $propertySchema = new \ArrayObject($propertySchema);
+ } else {
+     $propertySchema = new \ArrayObject($propertySchema + $valueSchema);
+ }

Which means the following: if we have other keys in $propertySchema- we don't add $ref from $valueSchema that will override everything.

For those, who already faced this issue, here is a workaround with decorating a service with this bug:

Details

First, we need to create a decorator:

<?php

declare(strict_types=1);

namespace App\JsonSchema;

use ApiPlatform\Core\JsonSchema\Schema;
use ApiPlatform\Core\JsonSchema\SchemaFactory as BaseSchemaFactory;
use ApiPlatform\Core\JsonSchema\SchemaFactoryInterface;
use function array_key_exists;
use function count;

class SchemaFactory implements SchemaFactoryInterface
{
    private BaseSchemaFactory $schemaFactory;

    public function __construct(BaseSchemaFactory $schemaFactory)
    {
        $this->schemaFactory = $schemaFactory;
    }

    public function buildSchema(string $className, string $format = 'json', string $type = Schema::TYPE_OUTPUT, ?string $operationType = null, ?string $operationName = null, ?Schema $schema = null, ?array $serializerContext = null, bool $forceCollection = false): Schema
    {
        $schema = $this->schemaFactory->buildSchema(
            $className,
            $format,
            $type,
            $operationType,
            $operationName,
            $schema,
            $serializerContext,
            $forceCollection
        );

        // custom code to fix api-platform issue
        foreach ($schema->getDefinitions() as $definitionName => $definition) {
            if (array_key_exists('properties', $definition)) {
                foreach ($definition['properties'] as $propertyName => &$propertySchema) {
                    if (count($propertySchema) > 1 && array_key_exists('$ref', $propertySchema)) {
                        // remove incorrectly added $ref (schema) as we have custom definition - other keys
                        unset($propertySchema['$ref']);
                    }
                }
            }
        }

        return $schema;
    }

    public function addDistinctFormat(string $format): void
    {
        $this->schemaFactory->addDistinctFormat($format);
    }
}

and then register it in services.yaml:

services:
    App\JsonSchema\SchemaFactory:
        decorates: 'api_platform.json_schema.schema_factory'

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions