Skip to content

Commit a47896f

Browse files
author
Sean O'Brien
committed
bugfix: document type json body
1 parent eb0bc62 commit a47896f

File tree

5 files changed

+100
-6
lines changed

5 files changed

+100
-6
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[
2+
{
3+
"type": "bugfix",
4+
"category": "Api",
5+
"description": "Fixes bug in serializing Document type JSON bodies"
6+
}
7+
]

src/Api/Serializer/JsonBody.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,13 @@ public static function getContentType(Service $service)
4949
*
5050
* @return string
5151
*/
52-
public function build(Shape $shape, array $args)
52+
public function build(Shape $shape, array|string $args)
5353
{
54+
// For Document shapes, args might be any JSON value, not just arrays
55+
if ($shape['document'] ?? false) {
56+
return json_encode($args, JSON_THROW_ON_ERROR);
57+
}
58+
5459
$result = json_encode($this->format($shape, $args));
5560
return $result == '[]' ? '{}' : $result;
5661
}

src/Api/Serializer/RestJsonSerializer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public function __construct(
3131
$this->jsonFormatter = $jsonFormatter ?: new JsonBody($api);
3232
}
3333

34-
protected function payload(StructureShape $member, array $value, array &$opts)
34+
protected function payload(StructureShape $member, array|string $value, array &$opts)
3535
{
3636
$body = isset($value) ?
3737
((string) $this->jsonFormatter->build($member, $value))

tests/Api/Serializer/JsonBodyTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,4 +226,35 @@ public function testFormatsJsonDoesNotCreateReferences($def, $args, $result)
226226
$builtShape = $j->build($shape, $args);
227227
$this->assertEquals($result, $builtShape);
228228
}
229+
230+
/**
231+
* @param $args
232+
* @param $expected
233+
*
234+
* @return void
235+
* @throws \JsonException
236+
* @dataProvider buildsDocTypesProvider
237+
*/
238+
public function testBuildsDocTypes($args, $expected): void
239+
{
240+
$j = new JsonBody(new Service([], function() { return []; }));
241+
$shape = Shape::create(
242+
[
243+
'type' => 'structure',
244+
'members' => [],
245+
'document' => true,
246+
]
247+
, new ShapeMap([])
248+
);
249+
$builtShape = $j->build($shape, $args);
250+
$this->assertEquals($expected, $builtShape);
251+
}
252+
253+
public function buildsDocTypesProvider(): iterable
254+
{
255+
return [
256+
['hello', '"hello"'],
257+
[['foo' => 'bar'], '{"foo":"bar"}']
258+
];
259+
}
229260
}

tests/Api/Serializer/RestJsonSerializerTest.php

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,21 @@ private function getTestService()
6666
'requestUri' => 'foo/{PathSegment}'
6767
],
6868
'input' => ['shape' => 'RequestUriOperationInput'],
69+
],
70+
'DocumentTypeAsPayload' => [
71+
'name' => 'DocumentTypeAsPayload',
72+
'http' => [
73+
'method' => 'PUT',
74+
'requestUri' => '/DocumentTypeAsPayload',
75+
'responseCode' => 200
76+
],
77+
'input' => [
78+
'shape' => 'DocumentTypeAsPayloadInputOutput'
79+
],
80+
'output' => [
81+
'shape' => 'DocumentTypeAsPayloadInputOutput'
82+
],
83+
'idempotent' => true
6984
]
7085
],
7186
'shapes' => [
@@ -83,6 +98,15 @@ private function getTestService()
8398
]
8499
]
85100
],
101+
'DocumentTypeAsPayloadInputOutput' => [
102+
'type' => 'structure',
103+
'members' => [
104+
'documentValue' => [
105+
'shape' => 'DocumentType'
106+
]
107+
],
108+
'payload' => 'documentValue'
109+
],
86110
'RequestUriOperationInput' => [
87111
'required' => ['PathSegment'],
88112
'type' => 'structure',
@@ -94,9 +118,10 @@ private function getTestService()
94118
'baz' => ['shape' => 'BazShape']
95119
]
96120
],
97-
"DocumentType" => [
98-
"type" => "structure",
99-
"document" => true
121+
'DocumentType' => [
122+
'type' => 'structure',
123+
'members' => [],
124+
'document' => true,
100125
],
101126
'BarInput' => [
102127
'type' => 'structure',
@@ -328,10 +353,36 @@ public function doctypeTestProvider() {
328353
]
329354
],
330355
'{"DocumentValue":{"DocumentType":2}}'
331-
],
356+
]
332357
];
333358
}
334359

360+
/**
361+
* @param $input
362+
* @param $expectedOutput
363+
*
364+
* @return void
365+
* @dataProvider handlesDocTypeAsPayloadProvider
366+
*/
367+
public function testHandlesDocTypeAsPayload($input, $expectedOutput): void
368+
{
369+
$request = $this->getRequest('DocumentTypeAsPayload', ['documentValue' => $input]);
370+
$this->assertSame('PUT', $request->getMethod());
371+
$this->assertSame('http://foo.com/DocumentTypeAsPayload', (string) $request->getUri());
372+
$this->assertSame($expectedOutput, $request->getBody()->getContents());
373+
$this->assertSame(
374+
'application/json',
375+
$request->getHeaderLine('Content-Type')
376+
);
377+
}
378+
379+
public function handlesDocTypeAsPayloadProvider(): iterable
380+
{
381+
return [
382+
['hello', '"hello"'],
383+
[['foo' => 'bar'], '{"foo":"bar"}']
384+
];
385+
}
335386

336387
/**
337388
* @dataProvider restJsonContentTypeProvider

0 commit comments

Comments
 (0)