Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Serializer] Upgrade to 7.1 - NotNormalizableValueException with $useMessageForUser=true - message lost #57427

Closed
@yblatti

Description

@yblatti

Symfony version(s) affected

7.1.1

Description

This concerns the denormalisation of a nested object using a custom (de)normalizer and COLLECT_DENORMALIZATION_ERRORS=true.

In Symfony 6.4 & 7.0, when a custom (de)normalizer throws a NotNormalizableValueException with $useMessageForUser = true in the denormalize() function, if Symfony Serializer’s context is set with DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true, it throws a PartialDenormalizationException and uses message, path, and expectedTypes defined in NotNormalizableValueException::createForUnexpectedDataType() to inform the user.

In Symfony 7.1, a broader message is generated using the class of the nested object, and loses the valuable information given by the custom normalizer.


Code in a minimalistic Normalizer

    public function denormalize(mixed $data, string $type, string $format = null, array $context = []): MySpecialDTO
    {
        $mySpecialDTO = new MySpecialDTO();

        $valueThatNeedsProcessing = $data['key'];
        if ('goodValue' !== $valueThatNeedsProcessing) {
            // ****************************************************************
            // The values & message set here used to be forwarded to client.
            // Not anymore on 7.1.
            // ****************************************************************
            throw NotNormalizableValueException::createForUnexpectedDataType('A clear message for the end user', 'Sample', ['ValidTypeIExpect'], $context['deserialization_path'].'.key', true);
        }

        $mySpecialDTO->key = $valueThatNeedsProcessing;

        return $mySpecialDTO;
    }

Symfony 6.4 & 7.0 output, with desired message :

{
    "type": "https:\/\/symfony.com\/errors\/validation",
    "title": "Validation Failed",
    "status": 422,
    "detail": "mySpecialField.key: This value should be of type ValidTypeIExpect.",
    "violations": [
        {
            "propertyPath": "mySpecialField.key",
            "title": "This value should be of type ValidTypeIExpect.",
            "template": "This value should be of type {{ type }}.",
            "parameters": {
                "{{ type }}": "ValidTypeIExpect"
            },
            "hint": "A clear message for the end user"
        }
    ]
}

Symfony 7.1 output, with a broader message:

{
    "type": "https:\/\/symfony.com\/errors\/validation",
    "title": "Validation Failed",
    "status": 422,
    "detail": "mySpecialField: This value should be of type App\\DTO\\MySpecialDTO|null.",
    "violations": [
        {
            "propertyPath": "mySpecialField",
            "title": "This value should be of type App\\DTO\\MySpecialDTO|null.",
            "template": "This value should be of type {{ type }}.",
            "parameters": {
                "{{ type }}": "App\\DTO\\MySpecialDTO|null"
            }
        }
    ]
}

How to reproduce

I wrote a simple reproducer, here : https://github.com/yblatti/repro-denorm-error

You'll find relevant code in src/Controller, src/DTO and src/Serialization.

The same code is used, only the Symfony version changes accros 3 branches : sf_6.4, sf_7.0, sf_7.1,

To test on different versions :

git clone https://github.com/yblatti/repro-denorm-error.git
cd repro-denorm-error

# Symfony 6.4
git checkout origin/sf_6.4
composer install
bin/console cache:clear --env=test
bin/phpunit --testdox
# all green results

# Symfony 7.0
git checkout origin/sf_7.0
composer install
bin/console cache:clear --env=test
bin/phpunit --testdox
# all green results

# Symfony 7.1
git checkout origin/sf_7.1
composer install
bin/console cache:clear --env=test
bin/phpunit --testdox
# the second test fails, as the message set in NotNormalizableValueException::createForUnexpectedDataType() is not used

Possible Solution

No response

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions