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

[Serializer] Empty object + ObjectNormalizer + JSON encoder = empty JSON array #23019

Open
meyerbaptiste opened this Issue Jun 1, 2017 · 3 comments

Comments

Projects
None yet
6 participants
@meyerbaptiste
Contributor

meyerbaptiste commented Jun 1, 2017

Q A
Bug report? yes
Feature request? no
BC Break report? no
RFC? no
Symfony version >= 2.7

Let us take this small example with Melody:

<?php
<<<CONFIG
packages:
    - "symfony/serializer: ^3.3"
    - "symfony/property-access: ^3.3"
CONFIG;

$encoders = [new Symfony\Component\Serializer\Encoder\JsonEncoder()];
$normalizers = [new Symfony\Component\Serializer\Normalizer\ObjectNormalizer()];
$serializer = new Symfony\Component\Serializer\Serializer($normalizers, $encoders);

var_dump($serializer->serialize(new class {}, 'json')); // string(2) "[]"

As you can see the result is an empty array ([]) instead of an empty object ({}). IMO this behavior is an important problem and it should be considered as a bug.

This problem comes from the ObjectNormalizer class which returns an empty array so the JsonEncoder class returns an empty JSON array too:

var_dump(json_encode([])); // string(2) "[]"

One solution would be to pass an empty ArrayObject instance to the JsonEncoder class:

var_dump(json_encode(\new ArrayObject)); // string(2) "{}"

To arrive to this result, we have to change the contract of the NormalizerInterface::normalize() method to return an iterable (or a scalable as currently) instead of an array.

In addition, as discussed with @dunglas, this change would allow us to use generators with normalizers.

Then we would be able to adapt the ObjectNormalizer class to deal with an ArrayObject instance instead of an array. As you can imagine, it's a huge BC break but I don't have a better solution to fix this issue...

WDYT?

@chalasr

This comment has been minimized.

Show comment
Hide comment
@chalasr

chalasr Jun 1, 2017

Member

Couldn't a flag/context option be passed to the object normalizer, enabling normalization of empty objects as JSON objects? It would be set to false by default with a deprecation notice saying that it'll be default true in 4.0, and maybe remove it at the end?

Member

chalasr commented Jun 1, 2017

Couldn't a flag/context option be passed to the object normalizer, enabling normalization of empty objects as JSON objects? It would be set to false by default with a deprecation notice saying that it'll be default true in 4.0, and maybe remove it at the end?

@xabbuh xabbuh added this to the 2.7 milestone Jun 2, 2017

@simonwelsh

This comment has been minimized.

Show comment
Hide comment
@simonwelsh

simonwelsh Jul 23, 2018

This is still an issue in 4.1, and using an empty ArrayObject no longer works.

Using JSON_FORCE_OBJECT is not an option as it prevents you from ever returning a JSON array. A trimmed down example we have is:

[
  'details' => new \stdClass(),
  'prices' => [
    ['amount' => 12.00, 'symbol' => '$'],
  ],
]

This should encode to {"details":{},"prices":[{"amount":12,"symbol":"$"}]}

simonwelsh commented Jul 23, 2018

This is still an issue in 4.1, and using an empty ArrayObject no longer works.

Using JSON_FORCE_OBJECT is not an option as it prevents you from ever returning a JSON array. A trimmed down example we have is:

[
  'details' => new \stdClass(),
  'prices' => [
    ['amount' => 12.00, 'symbol' => '$'],
  ],
]

This should encode to {"details":{},"prices":[{"amount":12,"symbol":"$"}]}

@javiereguiluz

This comment has been minimized.

Show comment
Hide comment
@javiereguiluz

javiereguiluz Jul 23, 2018

Member

@chalasr about this comment:

Couldn't a flag/context option be passed to the object normalizer, enabling normalization of empty objects as JSON objects?

I'm probably missing something ... but the current behaviour looks like a bug to me. Empty PHP objects should generate empty JSON objects, not empty JSON arrays. The last example showed by @simonwelsh explains it well.

Member

javiereguiluz commented Jul 23, 2018

@chalasr about this comment:

Couldn't a flag/context option be passed to the object normalizer, enabling normalization of empty objects as JSON objects?

I'm probably missing something ... but the current behaviour looks like a bug to me. Empty PHP objects should generate empty JSON objects, not empty JSON arrays. The last example showed by @simonwelsh explains it well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment