Skip to content

Symfony\Component\Serializer\Normalizer\PropertyNormalizer is unable to construct object without properties #46280

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
olsavmic opened this issue May 6, 2022 · 8 comments · May be fixed by #46417

Comments

@olsavmic
Copy link
Contributor

olsavmic commented May 6, 2022

Description

Symfony\Component\Serializer\Normalize\PropertyNormalizer is unable to construct object without any properties due to the check in PropertyNormalizer::supportsNormalization.

I don't see any reason to enforce this except for preventing programmers' errors, especially since the ObjectNormalizer does not impose such restrictions.

I can see legit use-cases in places like message queues where all required information is present in the message header and hence the body can be empty.

I'd suggest making this restriction in PropertyNormalizer optional as it removing it entirely could result in backward-incompatible change for very specific configurations (eg. someone might want to fallback to GetSetMethodNormalizer in case PropertyNormalizer fails)


(Similar situation applies to Symfony\Component\Serializer\Normalize\GetSetMethodNormalizer)

@mtarld
Copy link
Contributor

mtarld commented May 12, 2022

Hey @olsavmic, what do you mean when you say "without any properties", can you provide a tiny example?

@olsavmic
Copy link
Contributor Author

olsavmic commented May 13, 2022

Sure, when you try to serialize class without any properties:

class Foo {}

PropertyNormalizer won't be called (due to the check in PropertyNormalizer::supports) which means that the serializer would fail to construct the object.

If we remove this additional check from PropertyNormalizer, it can construct the object perfectly fine, including call to the constructor.

Replacing PropertyNormalizer by \Symfony\Component\Serializer\Normalizer\ObjectNormalizerwould solve this issue but we do not want to work with all the magic introduced byPropertyAccessor`, PropertyNormalizer perfectly fits our needs except for this edge case.


I simply think that the following check from \Symfony\Component\Serializer\Normalizer\PropertyNormalizer::supports is not needed or can be made optional:

    /**
     * Checks if the given class has any non-static property.
     */
    private function supports(string $class): bool
    {
        $class = new \ReflectionClass($class);

        // We look for at least one non-static property
        do {
            foreach ($class->getProperties() as $property) {
                if (!$property->isStatic()) {
                    return true;
                }
            }
        } while ($class = $class->getParentClass());

        return false;
    }

@mtarld
Copy link
Contributor

mtarld commented May 16, 2022

Indeed, I don't see any reason to enforce having at least one "non-static" property.
The same goes for the GetSetNormalizer

IMHO, as you said, we might add a context value like SUPPORT_EMPTY_OBJECT (name can be challenged) in the PropertyNormalizer and in the GetSetNormalizer (that'll default to false) to allow skipping the extra-check in the supports method

Up for a PR? 😉

@carsonbot
Copy link

Hey, thanks for your report!
There has not been a lot of activity here for a while. Is this bug still relevant? Have you managed to find a workaround?

@carsonbot
Copy link

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

@olsavmic
Copy link
Contributor Author

Waiting for linked PR to be merged #46417

@carsonbot carsonbot removed the Stalled label Mar 16, 2023
@carsonbot
Copy link

Hey, thanks for your report!
There has not been a lot of activity here for a while. Is this bug still relevant? Have you managed to find a workaround?

@olsavmic
Copy link
Contributor Author

@nicolas-grekas @dunglas ping

The release of Symfony 7 is getting pretty close and the implementation of a fix for this issue has been approved as optional feature for v6 and default in v7 (#46417 (comment)).

Would you consider reviewing and releasing this change?
I'm open to any changes, we can keep the default value to FALSE in order to not change the behavior.

To overcome this limitation in the meantime, we're using a custom normalizer for empty objects, which introduces unnecessary logic and is not fully compatible with all the stuff that AbstractObjectNormalizer (which is implemented by PropertyNormalizer, GetSetMethodNormalizer and the more complex ObjectNormalizer) provides.

@carsonbot carsonbot removed the Stalled label Sep 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants