Skip to content

IBX-9678: JsonSerializableNormalizer return type mismatch causing 500 error #160

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

Sztig
Copy link

@Sztig Sztig commented Mar 12, 2025

🎫 Issue IBX-9678

Description:

JsonSerializableNormalizer is hint typed to return string but we also normalize objects like Money/Money that return an array. If we try to create an order through API on latest Ibexa 5.0 the order would get created but on the return we would get an 500 error. I have changed the hint type to cover array as well.

I have also added a test to cover this scenario. Rest package doest not uses moneyphp/money package anywhere directly so instead of adding a dependency I have created a dummy object with minimal implementation to simulate the behavior of real Money object that returns an array.

Discovered while testing https://github.com/ibexa/order-management/pull/137 on 5.0

For QA:

Documentation:

@Sztig Sztig requested a review from a team March 12, 2025 15:38
Copy link
Contributor

@barw4 barw4 left a comment

Choose a reason for hiding this comment

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

Maybe it's an overkill but it would be great to have an integration test with a bit more complicated case, like object that uses MoneyObjecy, please see https://github.com/ibexa/rest/blob/main/tests/integration/Serializer/SerializerTest.php

Maybe you could add another case there and use TestDataObject with MoneyObject.


namespace Ibexa\Tests\Rest\Output;

class MoneyObject implements \JsonSerializable
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
class MoneyObject implements \JsonSerializable
final class MoneyObject implements \JsonSerializable

* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
declare(strict_types=1);

@barw4 barw4 requested a review from a team March 12, 2025 16:09
use Ibexa\Tests\Rest\Output\MoneyObject;
use PHPUnit\Framework\TestCase;

class ArrayNormalizerTest extends TestCase
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
class ArrayNormalizerTest extends TestCase
final class ArrayNormalizerTest extends TestCase

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
*/
*/
declare(strict_types=1);

Copy link
Contributor

@Steveb-p Steveb-p left a comment

Choose a reason for hiding this comment

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

To be honest, whole JsonSerializableNormalizer class can be removed, as Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer already exists.

☝️ all we need to take care is to properly register this as a service (under a non-class id, with class declared, if using YAML service files) to the correct serializers.

Comment on lines +22 to +23
#[\ReturnTypeWillChange]
public function jsonSerialize()
Copy link
Contributor

Choose a reason for hiding this comment

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

You can narrow down the return type from an interface. This is allowed.

Suggested change
#[\ReturnTypeWillChange]
public function jsonSerialize()
/**
* @return array<mixed>
*/
public function jsonSerialize(): array

* {@inheritDoc}
*/
public function normalize($object, ?string $format = null, array $context = []): string
public function normalize($object, ?string $format = null, array $context = []): string|array
Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, we should remove the return type, as \JsonSerializable::jsonSerialize() method does not offer any guaranties about the returned type 😞

Suggested change
public function normalize($object, ?string $format = null, array $context = []): string|array
public function normalize($object, ?string $format = null, array $context = [])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants