Skip to content

Commit

Permalink
fix: Fixes serialization of invalid items (e.g., functions) to return…
Browse files Browse the repository at this point in the history
… empty array. (#18)
  • Loading branch information
gustavofreze authored Oct 5, 2024
1 parent 22006c2 commit 3cc2211
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 28 deletions.
10 changes: 3 additions & 7 deletions src/Internal/JsonSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,11 @@
{
public function serialize(array $data): string
{
$isSingleItem = count($data) === 1;
$dataToSerialize = $isSingleItem ? ($data[0] ?? null) : $data;
$isSingleItem = static fn(array $data): bool => array_keys($data) !== range(0, count($data) - 1);
$dataToSerialize = $isSingleItem($data) ? $data : ($data[0] ?? null);

$json = json_encode($dataToSerialize, JSON_PRESERVE_ZERO_FRACTION);

if (!is_string($json) || $json === 'null') {
return $isSingleItem ? '{}' : '[]';
}

return $json;
return is_string($json) ? $json : '{}';
}
}
2 changes: 1 addition & 1 deletion tests/IterableSerializerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public function testSerializeMultipleInvalidItemsReturnsEmptyJsonArray(): void
$actual = $serializer->toJson();

/** @Then the output should be an empty JSON array */
self::assertSame('[[],[]]', $actual);
self::assertSame('[]', $actual);
}

public static function toJsonDataProvider(): array
Expand Down
17 changes: 17 additions & 0 deletions tests/Models/Serializable/Decimal.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace TinyBlocks\Serializer\Models\Serializable;

use TinyBlocks\Serializer\Serializer;
use TinyBlocks\Serializer\SerializerAdapter;

final readonly class Decimal implements Serializer
{
use SerializerAdapter;

public function __construct(public float $value)
{
}
}
49 changes: 29 additions & 20 deletions tests/SerializerAdapterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,45 +9,46 @@
use TinyBlocks\Serializer\Models\Serializable\Address;
use TinyBlocks\Serializer\Models\Serializable\Addresses;
use TinyBlocks\Serializer\Models\Serializable\Country;
use TinyBlocks\Serializer\Models\Serializable\Decimal;
use TinyBlocks\Serializer\Models\Serializable\Service;
use TinyBlocks\Serializer\Models\Serializable\Shipping;
use TinyBlocks\Serializer\Models\Serializable\State;

final class SerializerAdapterTest extends TestCase
{
#[DataProvider('shippingDataProviderForArray')]
public function testSerializeToArray(Shipping $shipping, array $expected): void
#[DataProvider('dataProviderForToArray')]
public function testSerializeToArray(Serializer $object, array $expected): void
{
/** @When the toArray method is called on the Shipping object */
$actual = $shipping->toArray();
/** @When the toArray method is called on the object */
$actual = $object->toArray();

/** @Then the result should match the expected structure */
self::assertSame($expected, $actual);
}

#[DataProvider('shippingDataProviderForJson')]
public function testSerializeToJson(Shipping $shipping, string $expected): void
#[DataProvider('dataProviderForToJson')]
public function testSerializeToJson(Serializer $object, string $expected): void
{
/** @When the toJson method is called on the Shipping object */
$actual = $shipping->toJson();
/** @When the toJson method is called on the object */
$actual = $object->toJson();

/** @Then the result should match the expected JSON string */
self::assertJsonStringEqualsJsonString($expected, $actual);
}

public function testSerializeSingleInvalidItemReturnsEmptyJsonObject(): void
public function testSerializeSingleInvalidItemReturnsReturnsEmptyArray(): void
{
/** @Given a single invalid item (e.g., a function that cannot be serialized) */
$service = new Service(action: fn(): int => 0);

/** @When attempting to serialize the invalid item */
/** @When attempting to serialize the object with the invalid item */
$actual = $service->toJson();

/** @Then the output should be an empty JSON object */
self::assertSame('{}', $actual);
/** @Then the invalid item should be serialized as an empty array in the JSON output */
self::assertSame('{"action":[]}', $actual);
}

public static function shippingDataProviderForArray(): array
public static function dataProviderForToArray(): array
{
$shippingWithNoAddresses = new Shipping(id: 1, addresses: new Addresses());
$shippingWithSingleAddress = new Shipping(
Expand Down Expand Up @@ -87,12 +88,16 @@ public static function shippingDataProviderForArray(): array
);

return [
'Decimal object' => [
'object' => new Decimal(value: 9.99),
'expected' => ['value' => 9.99]
],
'Shipping object with no addresses' => [
'shipping' => $shippingWithNoAddresses,
'object' => $shippingWithNoAddresses,
'expected' => ['id' => 1, 'addresses' => []]
],
'Shipping object with a single address' => [
'shipping' => $shippingWithSingleAddress,
'object' => $shippingWithSingleAddress,
'expected' => [
'id' => 2,
'addresses' => [
Expand All @@ -107,7 +112,7 @@ public static function shippingDataProviderForArray(): array
]
],
'Shipping object with multiple addresses' => [
'shipping' => $shippingWithMultipleAddresses,
'object' => $shippingWithMultipleAddresses,
'expected' => [
'id' => 100000,
'addresses' => [
Expand All @@ -131,15 +136,19 @@ public static function shippingDataProviderForArray(): array
];
}

public static function shippingDataProviderForJson(): array
public static function dataProviderForToJson(): array
{
return [
'Decimal object' => [
'object' => new Decimal(value: 9.99),
'expected' => '{"value":9.99}'
],
'Shipping object with no addresses' => [
'shipping' => new Shipping(id: 1, addresses: new Addresses()),
'object' => new Shipping(id: 1, addresses: new Addresses()),
'expected' => '{"id":1,"addresses":[]}'
],
'Shipping object with a single address' => [
'shipping' => new Shipping(
'object' => new Shipping(
id: 2,
addresses: new Addresses(
elements: [
Expand All @@ -156,7 +165,7 @@ public static function shippingDataProviderForJson(): array
'expected' => '{"id":2,"addresses":[{"city":"São Paulo","state":"SP","street":"Avenida Paulista","number":100,"country":"BR"}]}'
],
'Shipping object with multiple addresses' => [
'shipping' => new Shipping(
'object' => new Shipping(
id: 100000,
addresses: new Addresses(
elements: [
Expand Down

0 comments on commit 3cc2211

Please sign in to comment.