Skip to content

[Serializer] Add support for extending stdClass objects #54613

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
template-provider opened this issue Apr 16, 2024 · 11 comments
Closed

[Serializer] Add support for extending stdClass objects #54613

template-provider opened this issue Apr 16, 2024 · 11 comments

Comments

@template-provider
Copy link

Symfony version(s) affected

6.4

Description

The serialize and unserialize for stdClass works because of this code in the class ObjectNormalizer + method extractAttributes

        if (\stdClass::class === $object::class) {
            return array_keys((array) $object);
        }

but this code does not check for classes, that are extending stdClass.

How to reproduce

<?php

declare(strict_types = 1);

use stdClass;

class Contact extends stdClass
{
    public string $email = '';
}
        $encoders = [new JsonEncoder()];

        $classMetadataFactory = new ClassMetadataFactory(new AttributeLoader());
        $metadataAwareNameConverter = new MetadataAwareNameConverter($classMetadataFactory);
        $extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);

        $objectNormalizer =  new ObjectNormalizer(
            classMetadataFactory: $classMetadataFactory,
            nameConverter: $metadataAwareNameConverter,
            propertyTypeExtractor: $extractor,
            defaultContext: [
                AbstractObjectNormalizer::SKIP_UNINITIALIZED_VALUES => true,
                AbstractObjectNormalizer::SKIP_NULL_VALUES => true,
                AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT => true,
            ],
        );

        $normalizers = [
            $objectNormalizer,
        ];

        $serializer = new Serializer($normalizers, $encoders)

$contact = new Contact();
$contact->email = 'foo@example.com';
$contact->foo = 'bar';

$serializer->serialize($contact, 'json')

Possible Solution

Better would be some additional code like this:

        $classParents = class_parents($object::class);
        if (false !== $classParents && in_array(\stdClass::class, $classParents)) {
            return array_keys((array) $object);
        }

Additional Context

No response

@alexandre-daubois
Copy link
Member

What about classes extending stdClass and also defining other properties, public or not, with getters/setters? Just casting the object with as it is done with stdClass wouldn't fully work, isn't it?

@template-provider
Copy link
Author

I am not 100 percent sure what you mean. A getter/setter does not change anything for unknown properties during serialize/unserialize. The only possible solution would be magic getters/setters to set the unknown property.
But I have not tested it yet and do not even know if symfony serializer works with __get and __set.
Could you provide an example what you mean plz?

@template-provider
Copy link
Author

And as described above the problem is in unserialize to. In this case the following lines:
https://github.com/symfony/property-access/blob/7.0/PropertyAccessor.php#L525

            } elseif ($object instanceof \stdClass && property_exists($object, $property)) {
                $object->$property = $value;
            } elseif (!$this->ignoreInvalidProperty) {

The property_exists might not be needed imho. "} elseif ($object instanceof \stdClass) {" works

@carsonbot
Copy link

Thank you for this suggestion.
There has not been a lot of activity here for a while. Would you still like to see this feature?
Every feature is developed by the community.
Perhaps someone would like to try?
You can read how to contribute to get started.

@jg-development
Copy link

Yes, we still need that Feature

@carsonbot carsonbot removed the Stalled label Oct 23, 2024
@xabbuh
Copy link
Member

xabbuh commented Oct 24, 2024

Someone will have to do the actual work. Feature requests don't resolve magically.

@jg-development
Copy link

@xabbuh
As I described above. The problem is with the "property_exists" call.

The property_exists might not be needed imho. "} elseif ($object instanceof \stdClass) {" works

@xabbuh
Copy link
Member

xabbuh commented Oct 24, 2024

Please send a PR with the changes that you have in mind to move things forward.

@carsonbot
Copy link

Thank you for this suggestion.
There has not been a lot of activity here for a while. Would you still like to see this feature?
Every feature is developed by the community.
Perhaps someone would like to try?
You can read how to contribute to get started.

@carsonbot
Copy link

Hello? This issue is about to be closed if nobody replies.

@carsonbot
Copy link

Hey,

I didn't hear anything so I'm going to close it. Feel free to comment if this is still relevant, I can always reopen!

@carsonbot carsonbot closed this as not planned Won't fix, can't repro, duplicate, stale May 23, 2025
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