Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[Serializer] Add support for preserving empty object in object property#42240

Merged
fabpot merged 1 commit into
symfony:5.4symfony/symfony:5.4from
lyrixx:serializer-maplyrixx/symfony:serializer-mapCopy head branch name to clipboard
Jul 25, 2021
Merged

[Serializer] Add support for preserving empty object in object property#42240
fabpot merged 1 commit into
symfony:5.4symfony/symfony:5.4from
lyrixx:serializer-maplyrixx/symfony:serializer-mapCopy head branch name to clipboard

Conversation

@lyrixx

@lyrixx lyrixx commented Jul 23, 2021

Copy link
Copy Markdown
Member
Q A
Branch? 5.4
Bug fix? no
New feature? yes
Deprecations?
Tickets Fix #38192
License MIT
Doc PR

This PR leverage https://symfony.com/blog/new-in-symfony-5-3-inlined-serialization-context to fix #38192.

Example:

class MyDto
{
    public function __construct(
        #[Context([AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS => true ])]
        public array $mapWithOption = [],
        #[Context([AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS => true ])]
        public array $mapWithOptionAndData = ['foo' => 'bar'],
        public array $mapWithoutOption = [],
        public array $mapWithoutOptionAndData = ['foo' => 'bar'],
    ) {
    }
}

Will produce:

{"mapWithOption":{},"mapWithOptionAndData":{"foo":"bar"},"mapWithoutOption":[],"mapWithoutOptionAndData":{"foo":"bar"}}

@chalasr chalasr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

👍

@Nyholm Nyholm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I read the PR title and I was mentally preparing for reviewing a 500+ lines PR of complicated Serializer code.

This looks great. Well done.

Maybe we should take a short moment to discuss the name PRESERVE_EMPTY_OBJECTS. Im not sure it is perfect, but I don't have any suggestions Im more comfortable with.
Maybe FORCE_EMPTY_ARRAYS_AS_OBJECT.. Or EMPTY_MAP_AS_OBJECT... hm..

Did you consider anything else before deciding on PRESERVE_EMPTY_OBJECTS?

@lyrixx

lyrixx commented Jul 25, 2021

Copy link
Copy Markdown
Member Author

Did you consider anything else before deciding on PRESERVE_EMPTY_OBJECTS?

I did not introduce this constant. It exists for ages, with this exact purpose. 😁

@Nyholm

Nyholm commented Jul 25, 2021

Copy link
Copy Markdown
Member

Oh. Sorry. You are correct. Im all 👍🏽

@fabpot

fabpot commented Jul 25, 2021

Copy link
Copy Markdown
Member

Thank you @lyrixx.

@Foxprodev

Foxprodev commented Jul 26, 2021

Copy link
Copy Markdown
Contributor

Well. It's weird, starting from 5.4 I have to move from

class A {
    #[Context(normalizationContext: [AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS => true])]
    public ArrayObject $map;
    public function __construct()
    {
        $this->map = new ArrayObject();
        $this->map->append(new B());
    }
}
class B {
    public array $list = [];

    public array $anotherListMayBeEmpty;
    public function __construct()
    {
        $this->anotherListMayBeEmpty[] = new C();
    }
}
class C {
    public ArrayObject $index;

    public ArrayObject $settings;

    public ArrayObject $andSoOnObjects;

    public function __construct()
    {
        $this->index = new ArrayObject();
        $this->settings = new ArrayObject();
        $this->andSoOnObjects = new ArrayObject();
    }
}

to

class A {
    #[Context(normalizationContext: [AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS => true])]
    public ArrayObject $map;
    public function __construct()
    {
        $this->map = new ArrayObject();
        $this->map->append(new B());
    }
}
class B {
    #[Context(normalizationContext: [AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS => false])]
    public array $list = [];

    #[Context(normalizationContext: [AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS => false])]
    public array $anotherListMayBeEmpty;

    public function __construct()
    {
        $this->anotherListMayBeEmpty[] = new C();
    }
}
class C {
    #[Context(normalizationContext: [AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS => true])]
    public ArrayObject $index;

    #[Context(normalizationContext: [AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS => true])]
    public ArrayObject $settings;

    #[Context(normalizationContext: [AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS => true])]
    public ArrayObject $andSoOnObjects;

    public function __construct()
    {
        $this->index = new ArrayObject();
        $this->settings = new ArrayObject();
        $this->andSoOnObjects = new ArrayObject();
    }
}

Is it an expected complication? @lyrixx @chalasr @Nyholm
It was pretty expected behavior for me to separate list array's from indexed array's using OOP
That's why PRESERVE_EMPTY_OBJECTS was introduced ignoring just empty arrays.

if (is_iterable($data)) {
if (($context[AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS] ?? false) === true && $data instanceof \Countable && 0 === $data->count()) {
return $data;
}

This option is even named PRESERVE not FORCE like JSON_FORCE_OBJECT

P.S. I am using api-platform and there are so much serializeable nested classes in my projects...

@lyrixx

lyrixx commented Jul 27, 2021

Copy link
Copy Markdown
Member Author

I'll answer in the issue.

This was referenced Nov 5, 2021
javiereguiluz added a commit to symfony/symfony-docs that referenced this pull request Aug 8, 2022
…ect in example (alanpoulain)

This PR was merged into the 5.4 branch.

Discussion
----------

[Serializer] fix(serializer): missing empty_array_as_object in example

This PR:
- Replaces `empty_iterable_as_object` by `preserve_empty_objects`, like it should be.
- Adds `empty_array_as_object` to example in Serializer Context.
- Removes the mention `by default`, since it's `false` by default.

Related:
- #15554
- #15580
- symfony/symfony#42240
- symfony/symfony#42297

Commits
-------

cc54517 fix(serializer): missing empty_array_as_object in example
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.

[Serializer] Add a annotation (or something) to serialize empty collection as an object and not an array

7 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.