8000 [Serializer] Support `readonly` classes or classes that use readonly for constructor property promotion · Issue #49808 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Serializer] Support readonly classes or classes that use readonly for constructor property promotion #49808

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ruudk opened this issue Mar 25, 2023 · 6 comments

Comments

@ruudk
Copy link
Contributor
ruudk commented Mar 25, 2023

Description

The Serializer is perfectly capable of deserializing the following object without configuration:

final class CreateUserCommand
{
    private function __construct(
        public string $firstName,
        public string $lastName,
    ) {}
}

But as soon as you make the class readonly (PHP 8.2 feature) or make the constructor properties readonly (PHP 8.1) you'll get an error:

Error : Cannot initialize readonly property CreateUserCommand::$firstName from scope Symfony\Component\PropertyAccess\PropertyAccessor
 /Volumes/CS/www/cosmos/vendor/symfony/property-access/PropertyAccessor.php:530
final readonly class CreateUserCommand
{
    private function __construct(
        public string $firstName,
        public string $lastName,
    ) {}
}
final class CreateUserCommand
{
    private function __construct(
        public readonly string $firstName,
        public readonly string $lastName,
    ) {}
}

Example

No response

@ghost
Copy link
ghost commented Mar 25, 2023

I'm on PHP 8.1 and I write commands that are (de)serialized with public readonly promoted constructor properties and it's working fine. Are you sure you somehow didn't mess with the serializer configuration?

@ruudk
Copy link
Contributor Author
ruudk commented Mar 26, 2023

Thanks for your reply 😊
I'm not using any Serializer configuration at all. Do you? If so? What are you using? Do you maybe pass $context?

@ghost
Copy link
ghost commented Mar 27, 2023

I've just created a symfony/skeleton:^5.4 project, added symfony/serializer and symfony/property-access and successfully (de)serialized class with readonly properties.

See code
<?php

namespace App;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Serializer\SerializerInterface;

#[AsCommand(name: 'my-command')]
class MyCommand extends Command
{
    function __construct(
        private SerializerInterface $serializer
    ){
        parent::__construct();
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $a = new A('a', 1);
        $serialized = $this->serializer->serialize($a, 'json');
        dump($serialized);
        $deserialized = $this->serializer->deserialize($serialized, A::class, 'json');
        dump($deserialized);

        return 1;
    }
}

class A {
    function __construct(
        public readonly string $field1,
        public readonly int $field2,
    ) {}
}

Output:

^ "{"field1":"a","field2":1}"
^ App\A^ {#155
  +field1: "a"
  +field2: 1
}

@kaznovac
Copy link
Contributor
kaznovac commented Apr 1, 2023

@ruudk Have you used class inheritance and parent constructor call?

I've described a similar issue here #49450 (solved by having context ignore the problematic attribute - at not the most intuitive place, somewhere deep in deserialization service...)

@xabbuh
Copy link
Member
xabbuh commented Apr 16, 2023

I am going to close here for now due to the lack of feedback. Please let us know when you have more information and we can consider to reopen.

@xabbuh xabbuh closed this as not planned Won't fix, can't repro, duplicate, stale Apr 16, 2023
@wouterj
Copy link
Member
wouterj commented Apr 17, 2023

For reference, I also encountered a different error using read-only CPP properties that was caused by a seemingly unrelated name converter bug: #50042

As the ObjectNormalizer falls back to properties when it can't correctly handle a constructor, such bugs went unnoticed until now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants
0