api-platform: ApiResource parameters denormalizationContext and normalizationContext doesn't affect

API Platform version(s) affected: 2.6.4 Everything ok when you downgrade to 2.6.3

Description
ApiResource parameters denormalizationContext and normalizationContext doesn’t affect.

How to reproduce
In version 2.6.4 - swagger shows all fields and ignores denormalizationContext and normalizationContext But In versions before that, for example 2.6.3 - everything is ok. Swagger shows considering denormalizationContext and normalizationContext goups

How swagger looks with ApiPlatform version 2.6.3 image

Same code with 2.6.4 image

Original file is there: https://github.com/kadirov/api-starter-kit/blob/master/src/Entity/User.php


#[ApiResource(
    collectionOperations: [
        'get'                => [
            'security'              => "is_granted('ROLE_ADMIN')",
            'normalization_context' => ['groups' => ['users:read']],
        ],
        'post'               => [
            'controller' => UserCreateAction::class,
        ],
        'aboutMe'            => [
            'controller'      => UserAboutMeAction::class,
            'method'          => 'get',
            'path'            => 'users/about_me',
            'openapi_context' => [
                'summary'    => 'Shows info about the authenticated user',
            ],
        ],
        'auth'               => [
            'controller'      => UserAuthAction::class,
            'method'          => 'post',
            'path'            => 'users/auth',
            'openapi_context' => ['summary' => 'Authorization'],
        ],
        'authByRefreshToken' => [
            'controller'      => UserAuthByRefreshTokenAction::class,
            'method'          => 'post',
            'path'            => 'users/auth/refreshToken',
            'openapi_context' => ['summary' => 'Authorization by refreshToken'],
            'input'           => RefreshTokenRequestDto::class,
        ],
        'isUniqueEmail'      => [
            'controller'              => UserIsUniqueEmailAction::class,
            'method'                  => 'post',
            'path'                    => 'users/is_unique_email',
            'openapi_context'         => ['summary' => 'Checks email for uniqueness'],
            'denormalization_context' => ['groups' => ['user:isUniqueEmail:write']],
        ],
    ],
    itemOperations: [
        'changePassword' => [
            'controller'              => UserChangePasswordAction::class,
            'method'                  => 'put',
            'path'                    => 'users/{id}/password',
            'security'                => "object == user || is_granted('ROLE_ADMIN')",
            'openapi_context'         => ['summary' => 'Changes password'],
            'denormalization_context' => ['groups' => ['user:changePassword:write']],
        ],
        'delete'         => [
            'controller' => DeleteAction::class,
            'security'   => "object == user || is_granted('ROLE_ADMIN')",
        ],
        'get'            => [
            'security' => "object == user || is_granted('ROLE_ADMIN')",
        ],
        'put'            => [
            'security'                => "object == user || is_granted('ROLE_ADMIN')",
            'denormalization_context' => ['groups' => ['user:put:write']],
        ],
    ],
    denormalizationContext: ['groups' => ['user:write']],
    normalizationContext: ['groups' => ['user:read', 'users:read']],
)]
#[ApiFilter(OrderFilter::class, properties: ['id', 'createdAt', 'updatedAt', 'email'])]
#[ApiFilter(SearchFilter::class, properties: ['id' => 'exact', 'email' => 'partial'])]
#[UniqueEntity('email', message: 'This email is already used')]

/**
 * @ORM\Entity(repositoryClass=UserRepository::class)
 */
class User implements
    UserInterface,
    UpdatedAtSettableInterface,
    CreatedAtSettableInterface,
    IsDeletedSettableInterface
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    #[Groups(['users:read'])]
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    #[Assert\Email]
    #[Groups(['users:read', 'user:write', 'user:put:write', 'user:isUniqueEmail:write'])]
    private $email;

    /**
     * @ORM\Column(type="string", length=255)
     */
    #[Groups(['user:write', 'user:changePassword:write'])]
    private $password;

    /**
     * @ORM\Column(type="array")
     */
    #[Groups(['user:read'])]
    private $roles = [];

    /**
     * @ORM\Column(type="datetime")
     */
    #[Groups(['user:read'])]
    private $createdAt;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     * @Groups({"user:read"})
     */
    #[Groups(['user:read'])]
    private $updatedAt;

    /**
     * @ORM\Column(type="boolean")
     */
    private $isDeleted = false;

   // here getter and setter methods...
}

Possible Solution
Downgrade to 2.6.3

Additional Context
Symfony version 5.2.6 PHP version 8.0.3 OS: tested on windows 10, Fedora 33, docker with Debian 10

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 5
  • Comments: 26 (4 by maintainers)

Most upvoted comments

Same problem here, downgrading to 2.6.3 works

thanks @alanpoulain its fixed as you said 👍

Make sure you cache is cleared. Something is wrong in your project, you can try it on a new project, you will see that the issue is gone.

@alanpoulain I can confirm that the different issues I had around this problem have been fixed in 2.6.5

I don’t see the bug anymore in 2.6.5. @kadirov if I take your example.

2.6.4 image

2.6.5 image

PS: v2.6.5 this is still not fixed

How they not see yet this bug?

Btw, if anyone wants to do some digging, since the problem occurs between 2.6.3 and 2.6.4, here is the diff: https://github.com/api-platform/core/compare/v2.6.3...v2.6.4

From that diff, https://github.com/api-platform/core/pull/4138 looks particularly interesting. If someone having this issue could try to “revert” that PR manually on their local copy… to see if it makes any difference, that might help things 😃.

Cheers!

Same problem here

Still have an issue with this example on Symfony 6 and version 2.6.8.

textDescription field does not appears in Swagger documentation for write model.

<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use App\Repository\CheeseListingRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;

#[ORM\Entity(repositoryClass: CheeseListingRepository::class)]
#[ApiResource(
    shortName: "cheeses",
    denormalizationContext: ['groups' => ['write']],
    normalizationContext: ['groups' => ['read']],
)]
class CheeseListing
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    #[Groups(["read","write"])]
    private ?string $title = null;

    #[ORM\Column(type: Types::TEXT)]
    #[Groups(["read"])]
    private ?string $description = null;

    #[ORM\Column]
    #[Groups(["read","write"])]
    private ?int $price = null;

    #[ORM\Column]
    private ?\DateTimeImmutable $createdAt = null;

    #[ORM\Column]
    private bool $isPublished = false;

    public function __construct()
    {
        $this->createdAt = new \DateTimeImmutable();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getTitle(): ?string
    {
        return $this->title;
    }


    public function setTitle(string $title): self
    {
        $this->title = $title;

        return $this;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function setDescription(string $description): self
    {
        $this->description = $description;
        return $this;
    }

    #[Groups("write")]
    public function setTextDescription(string $description): self
    {
        $this->description = nl2br($description);
        return $this;
    }

    public function getPrice(): ?int
    {
        return $this->price;
    }

    public function setPrice(int $price): self
    {
        $this->price = $price;

        return $this;
    }

    #[Groups("read")]
    public function getCreatedAt(): ?\DateTimeImmutable
    {
        return $this->createdAt;
    }

    public function isIsPublished(): ?bool
    {
        return $this->isPublished;
    }


    public function setIsPublished(bool $isPublished): self
    {
        $this->isPublished = $isPublished;

        return $this;
    }
}

@rabraghib image

Please make sure:

  • Your entity has getters for your private properties:
    public function getId(): int
    {
        return $this->id;
    }

    public function getProp1(): string
    {
        return $this->prop1;
    }

    public function getProp2(): string
    {
        return $this->prop2;
    }

    public function getProp3(): string
    {
        return $this->prop3;
    }
  • You are using the last version of api-platform/core: docker-compose exec php composer req api-platform/core:^2.6.5

Then this might be related to https://github.com/api-platform/core/issues/4248 (or not)

for what it’s worth the controllers seem to be working just fine, the only real problem is the swagger UI displaying the wrong schema