Skip to content

Commit 3ba9475

Browse files
authored
Merge pull request #10 from WonderNetwork/feature/deserialize-nested-objects
Fix: deserializing nested objects
2 parents 8ca150a + bea244b commit 3ba9475

7 files changed

Lines changed: 65 additions & 7 deletions

File tree

src/Http/Serializer/DeserializeParameterResolver.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use ReflectionFunctionAbstract;
88
use ReflectionNamedType;
99
use Slim\Exception\HttpBadRequestException;
10+
use Symfony\Component\Serializer\Encoder\CsvEncoder;
11+
use Symfony\Component\Serializer\Encoder\JsonEncoder;
1012
use Symfony\Component\Serializer\Exception\ExceptionInterface;
1113
use Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException;
1214
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
@@ -50,10 +52,16 @@ public function getParameters(
5052
PayloadSource::Get => $request->getQueryParams(),
5153
};
5254

55+
$format = match ($attribute->source) {
56+
PayloadSource::Post => JsonEncoder::FORMAT,
57+
PayloadSource::Get => CsvEncoder::FORMAT,
58+
};
59+
5360
try {
5461
$resolvedParameters[$index] = $this->serializer->denormalize(
5562
$data,
5663
$parameterClass,
64+
format: $format,
5765
context: $attribute->context,
5866
);
5967
} catch (NotNormalizableValueException $e) {

src/ServiceFactory/SlimServiceFactory.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
use Slim\Middleware\ErrorMiddleware;
2020
use Slim\Psr7\Factory\ResponseFactory;
2121
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
22+
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
23+
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
2224
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
2325
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
2426
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
@@ -38,7 +40,12 @@ public function __invoke(ServicesBuilder $builder): iterable {
3840
yield Serializer::class => static fn () => new Serializer([
3941
new ArrayDenormalizer(),
4042
new ObjectNormalizer(
41-
propertyTypeExtractor: new PhpDocExtractor(),
43+
propertyTypeExtractor: new PropertyInfoExtractor(
44+
typeExtractors: [
45+
new PhpDocExtractor(),
46+
new ReflectionExtractor(),
47+
],
48+
),
4249
),
4350
]);
4451
yield DenormalizerInterface::class => get(Serializer::class);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WonderNetwork\SlimKernel\Http\Serializer;
6+
7+
final class BooleansInput {
8+
public bool $true;
9+
public bool $false;
10+
public bool $one;
11+
public bool $zero;
12+
}

tests/Http/Serializer/DeserializeParameterResolverTest.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,37 @@ public function testDeserialize(): void {
2424
['name' => 'cats'],
2525
['name' => 'dogs'],
2626
],
27+
'tag' => [
28+
'name' => 'alpha',
29+
],
2730
];
2831
$get = [
2932
'page' => 3,
33+
'lists' => ['alpha', 'bravo'],
34+
'arrays' => ['charlie' => 'delta'],
35+
'booleans' => [
36+
'true' => true,
37+
'false' => false,
38+
'one' => 1,
39+
'zero' => 0,
40+
],
3041
];
3142

3243
$request = (new ServerRequestFactory())
3344
->createServerRequest('GET', '/?'.http_build_query($get))
3445
->withParsedBody($post);
3546
$response = $app->handle($request);
47+
48+
$body = $response->getBody()->getContents();
49+
50+
self::assertSame(
51+
200,
52+
$response->getStatusCode(),
53+
$body,
54+
);
55+
3656
$actual = json_decode(
37-
$response->getBody()->getContents(),
57+
$body,
3858
associative: true,
3959
depth: 12,
4060
flags: JSON_THROW_ON_ERROR,

tests/Http/Serializer/EchoController.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ public function __invoke(
1212
#[Payload(source: PayloadSource::Get)] SampleGetInput $get,
1313
ResponseInterface $response,
1414
): ResponseInterface {
15-
return $response->withBody(
16-
(new StreamFactory())->createStream(
17-
json_encode(compact('post', 'get'), JSON_THROW_ON_ERROR),
18-
),
19-
);
15+
$streamFactory = new StreamFactory();
16+
$payload = compact('post', 'get');
17+
$json = json_encode($payload, JSON_THROW_ON_ERROR);
18+
$body = $streamFactory->createStream($json);
19+
20+
return $response->withBody($body);
2021
}
2122
}

tests/Http/Serializer/SampleGetInput.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,13 @@
66
final class SampleGetInput {
77
public int $page = 1;
88
public int $perPage = 100;
9+
/**
10+
* @var string[]
11+
*/
12+
public array $lists;
13+
/**
14+
* @var array<string, string>
15+
*/
16+
public array $arrays;
17+
public BooleansInput $booleans;
918
}

tests/Http/Serializer/SamplePostInput.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ final class SamplePostInput {
88
public int $value;
99
/** @var TagInput[] */
1010
public array $tags;
11+
public TagInput $tag;
1112
}

0 commit comments

Comments
 (0)