From 20f5111fbcc6c3f427bb62277f5a7d795e8ec8d7 Mon Sep 17 00:00:00 2001 From: Alex Wells Date: Thu, 19 Oct 2023 17:02:24 +0300 Subject: [PATCH] refactor: Allow any kind of date to be serialized with custom formatting --- .../Serialization/SerializerBuilder.php | 1 - .../TypeAdapter/Primitive/BuiltIn/Date.php | 13 +++++++ .../Primitive/BuiltIn/DateTimeMapper.php | 24 +++++++++---- .../Primitive/Carbon/CarbonMapper.php | 36 ------------------- tests/Integration/JsonSerializationTest.php | 32 ++++++++--------- 5 files changed, 47 insertions(+), 59 deletions(-) create mode 100644 src/GoodPhp/Serialization/TypeAdapter/Primitive/BuiltIn/Date.php delete mode 100644 src/GoodPhp/Serialization/TypeAdapter/Primitive/Carbon/CarbonMapper.php diff --git a/src/GoodPhp/Serialization/SerializerBuilder.php b/src/GoodPhp/Serialization/SerializerBuilder.php index d19c688..cc747de 100644 --- a/src/GoodPhp/Serialization/SerializerBuilder.php +++ b/src/GoodPhp/Serialization/SerializerBuilder.php @@ -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(), diff --git a/src/GoodPhp/Serialization/TypeAdapter/Primitive/BuiltIn/Date.php b/src/GoodPhp/Serialization/TypeAdapter/Primitive/BuiltIn/Date.php new file mode 100644 index 0000000..736ba9b --- /dev/null +++ b/src/GoodPhp/Serialization/TypeAdapter/Primitive/BuiltIn/Date.php @@ -0,0 +1,13 @@ +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); } } diff --git a/src/GoodPhp/Serialization/TypeAdapter/Primitive/Carbon/CarbonMapper.php b/src/GoodPhp/Serialization/TypeAdapter/Primitive/Carbon/CarbonMapper.php deleted file mode 100644 index 434b81c..0000000 --- a/src/GoodPhp/Serialization/TypeAdapter/Primitive/Carbon/CarbonMapper.php +++ /dev/null @@ -1,36 +0,0 @@ -toISOString(); - } - - #[MapFrom(PrimitiveTypeAdapter::class)] - public function fromCarbon(string $value): Carbon - { - return new Carbon($value); - } - - #[MapTo(PrimitiveTypeAdapter::class)] - public function toCarbonImmutable(CarbonImmutable $value): string - { - return $value->toISOString(); - } - - #[MapFrom(PrimitiveTypeAdapter::class)] - public function fromCarbonImmutable(string $value): CarbonImmutable - { - return new CarbonImmutable($value); - } -} diff --git a/tests/Integration/JsonSerializationTest.php b/tests/Integration/JsonSerializationTest.php index 091c78c..67c9bc5 100644 --- a/tests/Integration/JsonSerializationTest.php +++ b/tests/Integration/JsonSerializationTest.php @@ -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' => [ @@ -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' => [ @@ -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' => [ @@ -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' => [ @@ -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"}', ]; } @@ -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' => [ @@ -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' => [ @@ -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' => [ @@ -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' => [ @@ -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' => [ @@ -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"}', ]; } @@ -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' => [ @@ -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' => [ @@ -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' => [