Skip to content

Commit

Permalink
refactor: Allow any kind of date to be serialized with custom formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
autaut03 committed Oct 19, 2023
1 parent 86cd9af commit 20f5111
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 59 deletions.
1 change: 0 additions & 1 deletion src/GoodPhp/Serialization/SerializerBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ public function build(): Serializer
->addMapperLast(new ArrayMapper())
->addMapperLast(new CollectionMapper())
->addMapperLast(new DateTimeMapper())
->addMapperLast(new CarbonMapper())
->addFactoryLast(new ClassPropertiesPrimitiveTypeAdapterFactory(
new SerializedNameAttributeNamingStrategy($this->namingStrategy ?? BuiltInNamingStrategy::PRESERVING),
$this->hydrator ?? new ConstructorHydrator(),
Expand Down
13 changes: 13 additions & 0 deletions src/GoodPhp/Serialization/TypeAdapter/Primitive/BuiltIn/Date.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace GoodPhp\Serialization\TypeAdapter\Primitive\BuiltIn;

#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Date
{
public function __construct(
public readonly string $format,
)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,35 @@

namespace GoodPhp\Serialization\TypeAdapter\Primitive\BuiltIn;

use Carbon\Carbon;
use DateTime;
use DateTimeInterface;
use GoodPhp\Reflection\Reflection\Attributes\Attributes;
use GoodPhp\Reflection\Type\Type;
use GoodPhp\Serialization\TypeAdapter\Primitive\MapperMethods\Acceptance\BaseTypeAcceptedByAcceptanceStrategy;
use GoodPhp\Serialization\TypeAdapter\Primitive\MapperMethods\MapFrom;
use GoodPhp\Serialization\TypeAdapter\Primitive\MapperMethods\MapTo;
use GoodPhp\Serialization\TypeAdapter\Primitive\PrimitiveTypeAdapter;

final class DateTimeMapper
{
#[MapTo(PrimitiveTypeAdapter::class)]
public function to(DateTime $value): string
#[MapTo(PrimitiveTypeAdapter::class, new BaseTypeAcceptedByAcceptanceStrategy(DateTimeInterface::class))]
public function to(DateTimeInterface $value, Attributes $attributes): string
{
return $value->format(DateTimeInterface::RFC3339_EXTENDED);
$value = Carbon::createFromInterface($value);

$dateAttribute = $attributes->sole(Date::class);

return $dateAttribute ?
$value->format($dateAttribute->format) :
Carbon::instance($value)->toISOString();
}

#[MapFrom(PrimitiveTypeAdapter::class)]
public function from(string $value): DateTime
#[MapFrom(PrimitiveTypeAdapter::class, new BaseTypeAcceptedByAcceptanceStrategy(DateTimeInterface::class))]
public function from(string $value, Type $type): DateTimeInterface
{
return new DateTime($value);
$dateClass = $type->name;

return new $dateClass($value);
}
}

This file was deleted.

32 changes: 16 additions & 16 deletions tests/Integration/JsonSerializationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ public function serializesProvider(): Generator
yield 'DateTime' => [
DateTime::class,
new DateTime('2020-01-01 00:00:00'),
'"2020-01-01T00:00:00.000+00:00"',
'"2020-01-01T00:00:00.000000Z"',
];

yield 'nullable DateTime' => [
new NullableType(new NamedType(DateTime::class)),
new DateTime('2020-01-01 00:00:00'),
'"2020-01-01T00:00:00.000+00:00"',
'"2020-01-01T00:00:00.000000Z"',
];

yield 'nullable DateTime with null value' => [
Expand All @@ -114,7 +114,7 @@ public function serializesProvider(): Generator
new NamedType(DateTime::class)
),
[new DateTime('2020-01-01 00:00:00')],
'["2020-01-01T00:00:00.000+00:00"]',
'["2020-01-01T00:00:00.000000Z"]',
];

yield 'Collection of DateTime' => [
Expand All @@ -126,7 +126,7 @@ public function serializesProvider(): Generator
])
),
new Collection([new DateTime('2020-01-01 00:00:00')]),
'["2020-01-01T00:00:00.000+00:00"]',
'["2020-01-01T00:00:00.000000Z"]',
];

yield 'ClassStub with all fields' => [
Expand All @@ -146,7 +146,7 @@ public function serializesProvider(): Generator
new NestedStub('flattened'),
new CarbonImmutable('2020-01-01 00:00:00')
),
'{"primitive":1,"nested":{"Field":"something"},"date":"2020-01-01T00:00:00.000+00:00","optional":123,"nullable":123,"Field":"flattened","carbonImmutable":"2020-01-01T00:00:00.000000Z"}',
'{"primitive":1,"nested":{"Field":"something"},"date":"2020-01-01T00:00:00.000000Z","optional":123,"nullable":123,"Field":"flattened","carbonImmutable":"2020-01-01T00:00:00.000000Z"}',
];

yield 'ClassStub with empty optional and null nullable' => [
Expand All @@ -166,7 +166,7 @@ public function serializesProvider(): Generator
new NestedStub('flattened'),
new CarbonImmutable('2020-01-01 00:00:00')
),
'{"primitive":1,"nested":{"Field":"something"},"date":"2020-01-01T00:00:00.000+00:00","nullable":null,"Field":"flattened","carbonImmutable":"2020-01-01T00:00:00.000000Z"}',
'{"primitive":1,"nested":{"Field":"something"},"date":"2020-01-01T00:00:00.000000Z","nullable":null,"Field":"flattened","carbonImmutable":"2020-01-01T00:00:00.000000Z"}',
];
}

Expand Down Expand Up @@ -229,13 +229,13 @@ public function deserializesProvider(): Generator
yield 'DateTime' => [
DateTime::class,
new DateTime('2020-01-01 00:00:00'),
'"2020-01-01T00:00:00.000+00:00"',
'"2020-01-01T00:00:00.000000Z"',
];

yield 'nullable DateTime' => [
new NullableType(new NamedType(DateTime::class)),
new DateTime('2020-01-01 00:00:00'),
'"2020-01-01T00:00:00.000+00:00"',
'"2020-01-01T00:00:00.000000Z"',
];

yield 'nullable DateTime with null value' => [
Expand All @@ -261,7 +261,7 @@ public function deserializesProvider(): Generator
new NamedType(DateTime::class)
),
[new DateTime('2020-01-01 00:00:00')],
'["2020-01-01T00:00:00.000+00:00"]',
'["2020-01-01T00:00:00.000000Z"]',
];

yield 'Collection of DateTime' => [
Expand All @@ -273,7 +273,7 @@ public function deserializesProvider(): Generator
])
),
new Collection([new DateTime('2020-01-01 00:00:00')]),
'["2020-01-01T00:00:00.000+00:00"]',
'["2020-01-01T00:00:00.000000Z"]',
];

yield 'ClassStub with all fields' => [
Expand All @@ -293,7 +293,7 @@ public function deserializesProvider(): Generator
new NestedStub('flattened'),
new CarbonImmutable('2020-01-01 00:00:00')
),
'{"primitive":1,"nested":{"Field":"something"},"date":"2020-01-01T00:00:00.000+00:00","optional":123,"nullable":123,"Field":"flattened","carbonImmutable":"2020-01-01T00:00:00.000000Z"}',
'{"primitive":1,"nested":{"Field":"something"},"date":"2020-01-01T00:00:00.000000Z","optional":123,"nullable":123,"Field":"flattened","carbonImmutable":"2020-01-01T00:00:00.000000Z"}',
];

yield 'ClassStub with empty optional and null nullable' => [
Expand All @@ -313,7 +313,7 @@ public function deserializesProvider(): Generator
new NestedStub('flattened'),
new CarbonImmutable('2020-01-01 00:00:00')
),
'{"primitive":1,"nested":{"Field":"something"},"date":"2020-01-01T00:00:00.000+00:00","nullable":null,"Field":"flattened","carbonImmutable":"2020-01-01T00:00:00.000000Z"}',
'{"primitive":1,"nested":{"Field":"something"},"date":"2020-01-01T00:00:00.000000Z","nullable":null,"Field":"flattened","carbonImmutable":"2020-01-01T00:00:00.000000Z"}',
];

yield 'ClassStub with the least default fields' => [
Expand All @@ -333,7 +333,7 @@ public function deserializesProvider(): Generator
new NestedStub(),
new CarbonImmutable('2020-01-01 00:00:00')
),
'{"primitive":1,"nested":{},"date":"2020-01-01T00:00:00.000+00:00","carbonImmutable":"2020-01-01T00:00:00.000000Z"}',
'{"primitive":1,"nested":{},"date":"2020-01-01T00:00:00.000000Z","carbonImmutable":"2020-01-01T00:00:00.000000Z"}',
];
}

Expand Down Expand Up @@ -436,7 +436,7 @@ public function deserializesWithAnExceptionProvider(): Generator
PrimitiveType::array(
new NamedType(DateTime::class)
),
'["2020-01-01T00:00:00.000+00:00", null]',
'["2020-01-01T00:00:00.000000Z", null]',
];

yield 'associative array of DateTime' => [
Expand Down Expand Up @@ -483,7 +483,7 @@ public function deserializesWithAnExceptionProvider(): Generator
new NamedType(DateTime::class),
])
),
'{"primitive":"1","nested":{"Field":"something"},"date":"2020-01-01T00:00:00.000+00:00","carbonImmutable":"2020-01-01T00:00:00.000000Z"}',
'{"primitive":"1","nested":{"Field":"something"},"date":"2020-01-01T00:00:00.000000Z","carbonImmutable":"2020-01-01T00:00:00.000000Z"}',
];

yield 'ClassStub with wrong nested field type' => [
Expand All @@ -494,7 +494,7 @@ public function deserializesWithAnExceptionProvider(): Generator
new NamedType(DateTime::class),
])
),
'{"primitive":1,"nested":{"Field":123},"date":"2020-01-01T00:00:00.000+00:00","nullable":null,"carbonImmutable":"2020-01-01T00:00:00.000000Z"}',
'{"primitive":1,"nested":{"Field":123},"date":"2020-01-01T00:00:00.000000Z","nullable":null,"carbonImmutable":"2020-01-01T00:00:00.000000Z"}',
];

yield 'ClassStub with wrong nested array field type' => [
Expand Down

0 comments on commit 20f5111

Please sign in to comment.