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

Skip to content

[Serializer] Add SerializedPath annotation to flatten nested attributes #43534

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

Merged
merged 1 commit into from
Oct 23, 2022

Conversation

boenner
Copy link
Contributor

@boenner boenner commented Oct 15, 2021

Q A
Branch? 6.2
Bug fix? no
New feature? yes
Deprecations? no
Tickets Fix #32080
License MIT
Doc PR #17396

As suggested by @derrabus in #32080, I'm creating a PR for this.

In order to normalize/denormalize nested attributes, the @SerializedPath annotation can be used:

class NestedDummy
{
    /**
     * @SerializedPath("[one][two][three]")
     */
    public $foo;

    /**
     * @SerializedPath("[one][four]") 
     */
    public $bar;
}

with

$data = [
    'one' => [
        'two' => [
            'three' => 'foo',
        ],
        'four' => 'bar',
    ],
];
$normalizer = new AbstractObjectNormalizerWithMetadata();
$normalizer->denormalize(
    $data,
    NestedDummy::class,
    'any'
);

The annotations needs to be used with a valid PropertyPath string for this to work.

Open todos:

  • tests for new feature
  • update documentation

@boenner boenner requested a review from dunglas as a code owner October 15, 2021 17:53
@carsonbot carsonbot added this to the 5.4 milestone Oct 15, 2021
@carsonbot carsonbot changed the title [WIP] [Serializer] Flatten nested attributes [Serializer] [WIP] Flatten nested attributes Oct 15, 2021
@carsonbot
Copy link

Hey!

I see that this is your first PR. That is great! Welcome!

Symfony has a contribution guide which I suggest you to read.

In short:

  • Always add tests
  • Keep backward compatibility (see https://symfony.com/bc).
  • Bug fixes must be submitted against the lowest maintained branch where they apply (see https://symfony.com/releases)
  • Features and deprecations must be submitted against the 5.4 branch.

Review the GitHub status checks of your pull request and try to solve the reported issues. If some tests are failing, try to see if they are failing because of this change.

When two Symfony core team members approve this change, it will be merged and you will become an official Symfony contributor!
If this PR is merged in a lower version branch, it will be merged up to all maintained branches within a few days.

I am going to sit back now and wait for the reviews.

Cheers!

Carsonbot

@carsonbot
Copy link

Hey!

I think @jeroennoten has recently worked with this code. Maybe they can help review this?

Cheers!

Carsonbot

@OskarStark OskarStark changed the title [Serializer] [WIP] Flatten nested attributes [Serializer] [WIP] Flatten nested attributes Oct 17, 2021
@boenner boenner force-pushed the serializer-flatten-nested-attributes branch from 2758fde to fe5d453 Compare October 28, 2021 12:55
@fabpot fabpot modified the milestones: 5.4, 6.1 Oct 29, 2021
@boenner boenner force-pushed the serializer-flatten-nested-attributes branch 2 times, most recently from 02e59c6 to a824bd0 Compare November 2, 2021 15:18
@boenner boenner force-pushed the serializer-flatten-nested-attributes branch from fc0d799 to 9e6dd9a Compare November 17, 2021 10:19
@boenner
Copy link
Contributor Author

boenner commented Nov 17, 2021

I tried rebasing this from 5.4 to 6.0 by following the contribution guidelines but it seems like I screwed that up as things got a little messy ... is there any way I can salvage this PR or do I need to create a new one based on the 6.0 branch?

@boenner boenner force-pushed the serializer-flatten-nested-attributes branch 2 times, most recently from a15a534 to fdcc545 Compare November 17, 2021 16:17
@chalasr chalasr changed the base branch from 5.4 to 6.0 November 17, 2021 20:42
@chalasr chalasr force-pushed the serializer-flatten-nested-attributes branch from a15a534 to 992a563 Compare November 17, 2021 20:43
@chalasr
Copy link
Member

chalasr commented Nov 17, 2021

@boenner You only forgot to change the base branch of the pull request. I did it for you and squashed your commits to trigger the CI.

@boenner boenner force-pushed the serializer-flatten-nested-attributes branch from c210064 to 5d84bf2 Compare September 21, 2022 15:08
@nicolas-grekas nicolas-grekas force-pushed the serializer-flatten-nested-attributes branch 2 times, most recently from bd4277c to ef74981 Compare October 18, 2022 16:49
@nicolas-grekas
Copy link
Member

@boenner I just force-pushed on your fork to fix all comments from @mtarld but one. Can you please have a look?

@nicolas-grekas nicolas-grekas added the ❄️ Feature Freeze Important Pull Requests to finish before the next Symfony "feature freeze" label Oct 19, 2022
@boenner
Copy link
Contributor Author

boenner commented Oct 22, 2022

The review is finished and the SerializedPath annotation now uses the PropertyAccess component. Thanks for your help with the code changes, @mtarld!

@nicolas-grekas
Copy link
Member

Can you please update the PR's description if it's not in sync?

@nicolas-grekas nicolas-grekas force-pushed the serializer-flatten-nested-attributes branch from ceff3bd to 08a1119 Compare October 22, 2022 13:22
Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I force-pushed some CS changes. Failures are unrelated or false-positives (fabbot).

@fabpot
Copy link
Member

fabpot commented Oct 23, 2022

Thank you @boenner.

@fabpot fabpot merged commit 5131ec3 into symfony:6.2 Oct 23, 2022
@fabpot fabpot mentioned this pull request Oct 24, 2022
javiereguiluz added a commit to symfony/symfony-docs that referenced this pull request Nov 3, 2022
This PR was merged into the 6.2 branch.

Discussion
----------

[Serializer] SerializedPath documentation

Adds documentation for the `SerializedPath` annotation (symfony/symfony#43534). This fixes #17389.

Commits
-------

375c089 Documentation for the SerializedPath definition
eliashaeussler added a commit to eliashaeussler/composer-unused that referenced this pull request Dec 1, 2022
Since symfony/symfony#43534 (released with `symfony/serializer` 6.2.0),
Symfony's ObjectNormalizer has a hard dependency to the
`symfony/property-access` package. As we're using the ObjectNormalizer,
we must ensure to meet this requirement by explicitly adding the
package as requirement in `composer.json`.
icanhazstring pushed a commit to composer-unused/composer-unused that referenced this pull request Dec 1, 2022
Since symfony/symfony#43534 (released with `symfony/serializer` 6.2.0),
Symfony's ObjectNormalizer has a hard dependency to the
`symfony/property-access` package. As we're using the ObjectNormalizer,
we must ensure to meet this requirement by explicitly adding the
package as requirement in `composer.json`.
nicolas-grekas added a commit that referenced this pull request Mar 31, 2023
…enner)

This PR was merged into the 6.2 branch.

Discussion
----------

[Serializer] Fix serialized path for non-scalar values

| Q             | A
| ------------- | ---
| Branch?       | 6.2
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #49494
| License       | MIT
| Doc PR        | no

This relates to #49494 and #49225. When non-scalar values are normalized, they are normalized twice in the `normalize()` function:

```php
if (null !== $attributeValue && !\is_scalar($attributeValue)) {
	$stack[$attribute] = $attributeValue;
}
$data = $this->updateData($data, $attribute, $attributeValue, $class, $format, $attributeContext, $attributesMetadata, $classMetadata);
```

and a bit later:

```php
foreach ($stack as $attribute => $attributeValue) {
	...
	$data = $this->updateData($data, $attribute, $this->serializer->normalize($attributeValue, $format, $childContext), $class, $format, $attributeContext, $attributesMetadata, $classMetadata);
}
```

For non-scalar values with a `SerializedPath` annotation this leads to an exception because the serializer is trying to re-populate the path. Running `updateData()` only once fixes this, but breaks a couple of tests across the components as it changes the order of elements in the serialized string (non-scalar values will be pushed to the end). Other than the string comparisons, nothing seems to break. This was also an issue while reviewing the PR for the `SerializedPath` annotation (#43534 (comment)) and got reverted because of the potential BC break.

I'm not sure what benefit normalizing twice brings, so I added the test from `@HonzaMatosik`, changed the behavior in the normalizer and fixed the broken tests. If that's not the preferred solution here, I'd be ok with just eleminating the "The element you are trying to set is already populated" exception in the `SerializedPath` and allow overwriting values.

Commits
-------

d82ec41 [Serializer] Fix serializedpath for non scalar types
symfony-splitter pushed a commit to symfony/serializer that referenced this pull request Mar 31, 2023
…enner)

This PR was merged into the 6.2 branch.

Discussion
----------

[Serializer] Fix serialized path for non-scalar values

| Q             | A
| ------------- | ---
| Branch?       | 6.2
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #49494
| License       | MIT
| Doc PR        | no

This relates to symfony/symfony#49494 and symfony/symfony#49225. When non-scalar values are normalized, they are normalized twice in the `normalize()` function:

```php
if (null !== $attributeValue && !\is_scalar($attributeValue)) {
	$stack[$attribute] = $attributeValue;
}
$data = $this->updateData($data, $attribute, $attributeValue, $class, $format, $attributeContext, $attributesMetadata, $classMetadata);
```

and a bit later:

```php
foreach ($stack as $attribute => $attributeValue) {
	...
	$data = $this->updateData($data, $attribute, $this->serializer->normalize($attributeValue, $format, $childContext), $class, $format, $attributeContext, $attributesMetadata, $classMetadata);
}
```

For non-scalar values with a `SerializedPath` annotation this leads to an exception because the serializer is trying to re-populate the path. Running `updateData()` only once fixes this, but breaks a couple of tests across the components as it changes the order of elements in the serialized string (non-scalar values will be pushed to the end). Other than the string comparisons, nothing seems to break. This was also an issue while reviewing the PR for the `SerializedPath` annotation (symfony/symfony#43534 (comment)) and got reverted because of the potential BC break.

I'm not sure what benefit normalizing twice brings, so I added the test from `@HonzaMatosik`, changed the behavior in the normalizer and fixed the broken tests. If that's not the preferred solution here, I'd be ok with just eleminating the "The element you are trying to set is already populated" exception in the `SerializedPath` and allow overwriting values.

Commits
-------

d82ec41d18 [Serializer] Fix serializedpath for non scalar types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Serializer ❄️ Feature Freeze Important Pull Requests to finish before the next Symfony "feature freeze" Status: Reviewed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Serializer] @SerializedName flattening nested attributes
8 participants