Skip to content

[Serializer] Denormalize support for stdClass #52850

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

Open
wants to merge 1 commit into
base: 6.4
Choose a base branch
from

Conversation

nightio
Copy link

@nightio nightio commented Dec 1, 2023

Q A
Branch? 6.4
Bug fix? no
New feature? no
Deprecations? no
Issues -
License MIT

Add support for denormalizing stdClass objects in Symfony serializer

@nightio nightio requested a review from dunglas as a code owner December 1, 2023 13:30
@carsonbot carsonbot added this to the 6.4 milestone Dec 1, 2023
@nightio nightio force-pushed the denormalize-support-for-stdClass branch from 43d71df to 0479a92 Compare December 5, 2023 10:50
@nightio
Copy link
Author

nightio commented Jan 15, 2024

@dunglas could you make a code review and eventually merge the commit?

@chalasr chalasr modified the milestones: 6.4, 7.1 Jan 29, 2024
@nightio nightio force-pushed the denormalize-support-for-stdClass branch from 0479a92 to 0238782 Compare March 14, 2024 11:32
@nightio nightio force-pushed the denormalize-support-for-stdClass branch from 0238782 to 20a49a9 Compare March 14, 2024 12:53
@nightio nightio changed the title Denormalize support for std class [Serializer] Denormalize support for std class Mar 14, 2024
@nightio
Copy link
Author

nightio commented Mar 14, 2024

@nicolas-grekas Could you please make a review?

@stof
Copy link
Member

stof commented Mar 14, 2024

Instead of hacking that in the ObjectNormalizer, I think this should rather be a new Normalizer

@nightio
Copy link
Author

nightio commented Mar 14, 2024

@stof Good point. However, currently the normalizing process of stdClass is part of the same class - https://github.com/symfony/symfony/pull/52850/files#diff-397b4689ce56cc95e54911f6d78639bb3258a9ee9b36bfa06ec719e9635e6b1dR67

@nightio
Copy link
Author

nightio commented Apr 3, 2024

@stof I thought about it and think it should be part of the ObjectNormalizer.

  1. it is an object and, at the same time, the simplest object.
  2. Some bundles already use ObjectNormalizer to normalize properties of type stdClass, but it cannot be denormalized. e.g. https://github.com/dunglas/doctrine-json-odm - https://github.com/dunglas/doctrine-json-odm/blob/main/src/Bundle/Resources/config/services.xml

@stof @dunglas Could you please make a review and eventually merge it?

@stof
Copy link
Member

stof commented Apr 3, 2024

  1. it is an object and, at the same time, the simplest object.

if we go that way, all core normalizers would be removed by bundling them into ObjectNormalizer, because BackedEnum or DateTime are also objects.

ObjectNormalizer is not about being the implementation to use for all objects. It is the generic implementation used for objects that don't have another normalizer registered with a higher priority to take over the normalization with specific logic.

2. Some bundles already use ObjectNormalizer to normalize properties of type stdClass, but it cannot be denormalized.

The JSON ODM does not use the ObjectNormalizer directly. It uses a Serializer with multiple normalizers registered in it. This means that they could totally register the new normalizer once it is available. They already did exactly that for the BackedEnumNormalizer and the UidNormalizer btw.

@derrabus
Copy link
Member

derrabus commented Apr 3, 2024

I'm with @stof here. Adding special behavior for a specific class usually means we're adding a new normalizer.

@xabbuh xabbuh modified the milestones: 7.1, 7.2 May 15, 2024
@mtarld
Copy link
Contributor

mtarld commented Sep 18, 2024

Agreed as well. The ObjectNormalizer is kind of big enough...

Plus, a stdClass dedicated normalizer could be way faster than the ObjectNormalizer one.
Therefore, the developers willing to normalize stdClass only will be able to use this instead of the ObjectNormalizer one and have a performance boost, which is great!

@jg-development
Copy link

We have this problem too:
#54613
Is somebody already working on this normalizer? Otherwise if I have some time, I will step in.

@mtarld
Copy link
Contributor

mtarld commented Oct 29, 2024

AKAIK, there is no ongoing work on that normalizer, so feel free to step in 🙂

@jg-development
Copy link

Questions regarding "new normalizer". What about a class, that is a mixture of stdclass and object?

<?php

declare(strict_types = 1);

use stdClass;

class Contact extends stdClass
{
    public string $email = '';
}

I am not sure if a new normalizer is the best solution here.
I am not an expert in the normalizer logic, but the "StdClassNormalizer" cannot work with logic of the "ObjectNormalizer" + "AbstractObjectNormalizer".
"ObjectNormalizer" is a final class, so a new "StdClassNormalizer" has a lot of duplicate code from the "ObjectNormalizer".

But I will kick in and give feedback

jg-development pushed a commit to jg-development/symfony that referenced this pull request Nov 5, 2024
@jg-development
Copy link

Hi..
I added a pull (7.2) for adding the support of stdclasses. I added this feature directly into the objectnormalizer.

The problem with an extra stdclass normalizer is the shared logic of stdclass objects and objects that extends stdclasses.
In the end, we would have a lot of duplicate code in the StdclassNormalizer + ObjectNormalizer. And putting everything in the AbstractObjectNormalizer would have impact on the other normalizers (GetSetMethodNormalizer, PropertyNormalizer).

It should be possible to extract the stdclass logic into a StdclassNormalizer and extend the ObjectNormalizer.
But I am not an expert of this normalizers, so if somebody with more inside .... feel free to change the pull.

Imho the ObjectNormalizer needs an overhaul, but this is an issue for later and not for now. Maybe, than it is possible to seperate the normalizers.

@OskarStark OskarStark changed the title [Serializer] Denormalize support for std class [Serializer] Denormalize support for stdClass Nov 5, 2024
jg-development pushed a commit to jg-development/symfony that referenced this pull request Nov 5, 2024
jg-development pushed a commit to jg-development/symfony that referenced this pull request Nov 5, 2024
jg-development pushed a commit to jg-development/symfony that referenced this pull request Nov 5, 2024
@jg-development
Copy link

@dunglas
the coding style hates me, but the style problems are not within my code, but within existing code.
maybe execute coding style in another commit/issue.

@mtarld
Copy link
Contributor

mtarld commented Nov 15, 2024

What about acting directly on PropertyAccessor instead?

The actual behavior in PropertyAccessor is checking the following: $object instanceof \stdClass && property_exists($object, $property).
And it will work for dynamic properties if we only have checked $object instanceof \stdClass.

I'm still not sure why we need that property_exists check. I've seen most of them have been introduced in symfony/property-access@2d75186, so maybe you can help us @alexandre-daubois?

@alexandre-daubois
Copy link
Member

The property_exists is used to check whether a property with a . exists in the object or not. It is an edge case, only possible when casting an array to an object with (object) (and maybe with ArrayObjects?). If property_exists returns false, then this means we are actually dealing with a property path, not an actual property of the object. Again, this truly is an edge-case 😄

@jg-development
Copy link

@mtarld @alexandre-daubois
Thx for th info.... I always asked myself: why on earth was that property_exists added? ;-)

@fabpot fabpot modified the milestones: 7.2, 7.3 Nov 20, 2024
@fabpot fabpot modified the milestones: 7.3, 7.4 May 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants