Skip to content
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

Symfony Serializer is omitting attributes when using groups #54967

Closed
th-lange opened this issue May 17, 2024 · 4 comments
Closed

Symfony Serializer is omitting attributes when using groups #54967

th-lange opened this issue May 17, 2024 · 4 comments

Comments

@th-lange
Copy link

Symfony version(s) affected

7.0.7

Description

The symfony serializer behaves strangely. It serializes some grouped values depending on the order, they are serialized.

I use the example symfony project, where I created a controller:

File: Controller/FirstController.php

#[Route('/test')]
final class FirstController extends AbstractController
{
    public function __construct(
        private NormalizerInterface $normalizer,
        private SerializerInterface $serializer,
    )
    {
    }


    #[Route('/')]
    public function first(Request $request): Response
    {
        $example = new Example();
        $example->setContent('content')
            ->setAuthor('Author')
            ->setExampleName('Example 1')
            ->setText('Some Text');

        $noGroup = $this->normalizer->normalize($example, null, []);
        $example = $this->normalizer->normalize($example, null, [AbstractNormalizer::GROUPS => ['one']]);
        $example2 = $this->normalizer->normalize($example, null, [AbstractNormalizer::GROUPS => ['two']]);
        $example3 = $this->normalizer->normalize($example, null, [AbstractNormalizer::GROUPS => ['id']]);

        return new JsonResponse(
            [
                'noGroup' => $noGroup,
                'example' => $example,
                'example2' => $example2,
                'id' => $example3,
            ]
        );
    }
}

and a simple Entity: Entity/Example.php

class Example
{
    #[Groups(['id'])]
    private int $id;

    #[Ignore]
    private ?string $text = null;

    #[Groups(['one'])]
    private ?string $content = null;

    #[Groups(['two'])]
    private \DateTime $publishedAt;

    #[Groups(['two'])]
    private ?string $author = null;

    private ?string $exampleName = null;


    public function __construct()
    {
        $this->publishedAt = new \DateTime();
        $this->id = random_int(1, 999999999);
    }
   // add fluent getter / setter 
}

When the route "test" is called, the normalizer will give (what seems to me to be) an incorrect response:

{
  "noGroup": {
    "id": 350440471,
    "content": "content",
    "publishedAt": "2024-05-17T11:15:18+00:00",
    "author": "Author",
    "exampleName": "Example 1"
  },
  "example": {
    "content": "content"
  },
  "example2": {
    "content": "content"
  },
  "id": {
    "content": "content"
  }
}

This is confusing - because it seems like, the other groups are not considered, when serializing and everything is a "group one" case. If I change the order things are serialized (in the FirstController from (one, two, id) to (id, two, one) ), the normalizer gives a correct response:

{
  "noGroup": {
    "id": 680028014,
    "content": "content",
    "publishedAt": "2024-05-17T11:19:16+00:00",
    "author": "Author",
    "exampleName": "Example 1"
  },
  "example": {
    "content": "content"
  },
  "example2": {
    "publishedAt": "2024-05-17T11:19:16+00:00",
    "author": "Author"
  },
  "id": {
    "id": 680028014
  }
}

Is this a bug or am I missing something?

How to reproduce

  • Create a simple symfony project symfony new playground --version="7.0.*" --webapp
  • Install the serializer symfony composer require symfony/serializer
  • Install composer req. symfony composer install
  • Add the code snippets above
    • Generate getters and setters for Example.php
  • Start the server symfony server:start
  • Call the route

To verify inconsistent behavior, just shuffle the lines:

        $noGroup = $this->normalizer->normalize($example, null, []);
        $example = $this->normalizer->normalize($example, null, [AbstractNormalizer::GROUPS => ['one']]);
        $example2 = $this->normalizer->normalize($example, null, [AbstractNormalizer::GROUPS => ['two']]);
        $example3 = $this->normalizer->normalize($example, null, [AbstractNormalizer::GROUPS => ['id']]);

Possible Solution

No response

Additional Context

No response

@xabbuh
Copy link
Member

xabbuh commented May 17, 2024

Can you create a small example application that allows to reproduce your issue?

@th-lange
Copy link
Author

A small example can be found here:

@HypeMC
Copy link
Contributor

HypeMC commented May 27, 2024

@th-lange Maybe I misunderstood your issue, but the reason you're getting the "incorrect" response is that you're using the $example variable for two different purposes. After the first call to normalize(), the value of the variable becomes the result of that call, which is what you're then normalizing in all subsequent calls. Try doing the following:

diff --git a/src/Controller/FirstController.php b/src/Controller/FirstController.php
index 907cf11..a80c402 100644
--- a/src/Controller/FirstController.php
+++ b/src/Controller/FirstController.php
@@ -45,14 +45,14 @@ final class FirstController extends AbstractController
             ->setText('Some Text');
 
         $noGroup = $this->normalizer->normalize($example, null, []);
-        $example = $this->normalizer->normalize($example, null, [AbstractNormalizer::GROUPS => ['one']]);
+        $example1 = $this->normalizer->normalize($example, null, [AbstractNormalizer::GROUPS => ['one']]);
         $example2 = $this->normalizer->normalize($example, null, [AbstractNormalizer::GROUPS => ['two']]);
         $example3 = $this->normalizer->normalize($example, null, [AbstractNormalizer::GROUPS => ['id']]);
 
         return new JsonResponse(
             [
                 'noGroup' => $noGroup,
-                'example' => $example,
+                'example' => $example1,
                 'example2' => $example2,
                 'id' => $example3,
             ]

@xabbuh
Copy link
Member

xabbuh commented May 28, 2024

good catch @HypeMC, closing as explained then

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

4 participants