Skip to content

Commit af53a2d

Browse files
authored
Merge pull request #38 from pongee/jsonapi
Add "application/vnd.api+json" support
2 parents acfcc0a + ce7a791 commit af53a2d

File tree

15 files changed

+383
-112
lines changed

15 files changed

+383
-112
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7+
## [5.7.0] - 2021-05-28
8+
### Added
9+
- Support for `application/vnd.api+json` MIME type.
10+
711
## [5.6.1] - 2021-05-25
812
### Fixed
913
- Minimum and Maximum constraints work for floats
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file was generated by docler-labs/api-client-generator.
7+
*
8+
* Do not edit it manually.
9+
*/
10+
11+
namespace OpenApi\PetStoreClient\Serializer\ContentType;
12+
13+
use OpenApi\PetStoreClient\Schema\SerializableInterface;
14+
use Psr\Http\Message\StreamInterface;
15+
16+
abstract class AbstractJsonContentTypeSerializer implements ContentTypeSerializerInterface
17+
{
18+
private const JSON_DEPTH = 512;
19+
20+
private const JSON_OPTIONS = JSON_BIGINT_AS_STRING | JSON_PRESERVE_ZERO_FRACTION | JSON_UNESCAPED_UNICODE;
21+
22+
/**
23+
* @throws SerializeException
24+
*/
25+
public function encode(SerializableInterface $body): string
26+
{
27+
$encodedData = \json_encode($body->toArray(), self::JSON_OPTIONS);
28+
$lastErrorCode = \json_last_error();
29+
if ($lastErrorCode === JSON_ERROR_NONE && $encodedData !== false) {
30+
return $encodedData;
31+
}
32+
throw new SerializeException('JSON encode error: ' . $this->getErrorMessage($lastErrorCode));
33+
}
34+
35+
/**
36+
* @throws SerializeException
37+
*/
38+
public function decode(StreamInterface $body): array
39+
{
40+
$body->rewind();
41+
// According to RFC7159 a JSON value MUST be an object, array, number, string,
42+
// or one of the following three literal names: false, null, true.
43+
$result = \json_decode($body->getContents(), true, self::JSON_DEPTH, self::JSON_OPTIONS);
44+
$lastErrorCode = \json_last_error();
45+
if ($lastErrorCode === JSON_ERROR_NONE) {
46+
if (! \is_array($result)) {
47+
$result = [ContentTypeSerializerInterface::LITERAL_VALUE_KEY => $result];
48+
}
49+
50+
return $result;
51+
}
52+
throw new SerializeException('JSON decode error: ' . $this->getErrorMessage($lastErrorCode));
53+
}
54+
55+
private function getErrorMessage(int $errorCode): string
56+
{
57+
$errorMessages = [JSON_ERROR_NONE => 'No errors', JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch', JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON', JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded', JSON_ERROR_RECURSION => 'Recursive reference was found', JSON_ERROR_INF_OR_NAN => 'NaN or Inf was found', JSON_ERROR_UNSUPPORTED_TYPE => 'Unsupported type was found'];
58+
59+
return $errorMessages[$errorCode] ?? 'Unknown error';
60+
}
61+
}

example/gen/src/Serializer/ContentType/JsonContentTypeSerializer.php

+2-46
Original file line numberDiff line numberDiff line change
@@ -10,56 +10,12 @@
1010

1111
namespace OpenApi\PetStoreClient\Serializer\ContentType;
1212

13-
use OpenApi\PetStoreClient\Schema\SerializableInterface;
14-
use Psr\Http\Message\StreamInterface;
15-
16-
class JsonContentTypeSerializer implements ContentTypeSerializerInterface
13+
class JsonContentTypeSerializer extends AbstractJsonContentTypeSerializer
1714
{
18-
const MIME_TYPE = 'application/json';
19-
20-
const JSON_DEPTH = 512;
21-
22-
const JSON_OPTIONS = JSON_BIGINT_AS_STRING | JSON_PRESERVE_ZERO_FRACTION | JSON_UNESCAPED_UNICODE;
23-
24-
public function encode(SerializableInterface $body): string
25-
{
26-
$encodedData = \json_encode($body->toArray(), self::JSON_OPTIONS);
27-
$lastErrorCode = \json_last_error();
28-
if ($lastErrorCode === JSON_ERROR_NONE && $encodedData !== false) {
29-
return $encodedData;
30-
}
31-
throw new SerializeException('JSON encode error: ' . $this->getErrorMessage($lastErrorCode));
32-
}
33-
34-
/**
35-
* @throws SerializeException
36-
*/
37-
public function decode(StreamInterface $body): array
38-
{
39-
$body->rewind();
40-
// According to RFC7159 a JSON value MUST be an object, array, number, string,
41-
// or one of the following three literal names: false, null, true.
42-
$result = \json_decode($body->getContents(), true, self::JSON_DEPTH, self::JSON_OPTIONS);
43-
$lastErrorCode = \json_last_error();
44-
if ($lastErrorCode === JSON_ERROR_NONE) {
45-
if (! \is_array($result)) {
46-
$result = [ContentTypeSerializerInterface::LITERAL_VALUE_KEY => $result];
47-
}
48-
49-
return $result;
50-
}
51-
throw new SerializeException('JSON decode error: ' . $this->getErrorMessage($lastErrorCode));
52-
}
15+
public const MIME_TYPE = 'application/json';
5316

5417
public function getMimeType(): string
5518
{
5619
return self::MIME_TYPE;
5720
}
58-
59-
private function getErrorMessage(int $errorCode): string
60-
{
61-
$errorMessages = [JSON_ERROR_NONE => 'No errors', JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch', JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON', JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded', JSON_ERROR_RECURSION => 'Recursive reference was found', JSON_ERROR_INF_OR_NAN => 'NaN or Inf was found', JSON_ERROR_UNSUPPORTED_TYPE => 'Unsupported type was found'];
62-
63-
return $errorMessages[$errorCode] ?? 'Unknown error';
64-
}
6521
}

src/Command/GenerateCommand.php

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use DoclerLabs\ApiClientGenerator\MetaTemplateFacade;
1313
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\FormUrlencodedContentTypeSerializer;
1414
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\JsonContentTypeSerializer;
15+
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\VdnApiJsonContentTypeSerializer;
1516
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\XmlContentTypeSerializer;
1617
use DoclerLabs\ApiClientGenerator\Output\Meta\MetaFileCollection;
1718
use DoclerLabs\ApiClientGenerator\Output\MetaFilePrinter;
@@ -209,6 +210,7 @@ private function getBlacklistedFiles(Specification $specification): array
209210
XmlContentTypeSerializer::MIME_TYPE => XmlContentTypeSerializer::class,
210211
FormUrlencodedContentTypeSerializer::MIME_TYPE => FormUrlencodedContentTypeSerializer::class,
211212
JsonContentTypeSerializer::MIME_TYPE => JsonContentTypeSerializer::class,
213+
VdnApiJsonContentTypeSerializer::MIME_TYPE => VdnApiJsonContentTypeSerializer::class,
212214
];
213215

214216
$allContentTypes = $specification->getAllContentTypes();

src/Entity/Request.php

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use DoclerLabs\ApiClientGenerator\Input\InvalidSpecificationException;
88
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\FormUrlencodedContentTypeSerializer;
99
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\JsonContentTypeSerializer;
10+
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\VdnApiJsonContentTypeSerializer;
1011
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\XmlContentTypeSerializer;
1112

1213
class Request
@@ -31,6 +32,7 @@ class Request
3132
JsonContentTypeSerializer::MIME_TYPE,
3233
FormUrlencodedContentTypeSerializer::MIME_TYPE,
3334
XmlContentTypeSerializer::MIME_TYPE,
35+
VdnApiJsonContentTypeSerializer::MIME_TYPE,
3436
];
3537
private string $path;
3638
private string $method;

src/Generator/ServiceProviderGenerator.php

+13-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
use DoclerLabs\ApiClientGenerator\Ast\Builder\CodeBuilder;
77
use DoclerLabs\ApiClientGenerator\Ast\Builder\MethodBuilder;
88
use DoclerLabs\ApiClientGenerator\Entity\Field;
9-
use DoclerLabs\ApiClientGenerator\Entity\Operation;
109
use DoclerLabs\ApiClientGenerator\Generator\Implementation\ContainerImplementationStrategy;
1110
use DoclerLabs\ApiClientGenerator\Generator\Implementation\HttpMessageImplementationStrategy;
1211
use DoclerLabs\ApiClientGenerator\Input\Specification;
@@ -17,6 +16,7 @@
1716
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\BodySerializer;
1817
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\FormUrlencodedContentTypeSerializer;
1918
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\JsonContentTypeSerializer;
19+
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\VdnApiJsonContentTypeSerializer;
2020
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\XmlContentTypeSerializer;
2121
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\QuerySerializer;
2222
use DoclerLabs\ApiClientGenerator\Output\Php\PhpFileCollection;
@@ -50,6 +50,7 @@ public function generate(Specification $specification, PhpFileCollection $fileRe
5050
->addImport(CopiedNamespace::getImport($this->baseNamespace, BodySerializer::class))
5151
->addImport(CopiedNamespace::getImport($this->baseNamespace, QuerySerializer::class))
5252
->addImport(CopiedNamespace::getImport($this->baseNamespace, JsonContentTypeSerializer::class))
53+
->addImport(CopiedNamespace::getImport($this->baseNamespace, VdnApiJsonContentTypeSerializer::class))
5354
->addImport(CopiedNamespace::getImport($this->baseNamespace, FormUrlencodedContentTypeSerializer::class))
5455
->addImport(CopiedNamespace::getImport($this->baseNamespace, XmlContentTypeSerializer::class))
5556
->addImport(
@@ -219,9 +220,19 @@ private function generateBodySerializerClosure(Specification $specification): Cl
219220
);
220221
}
221222

223+
if (in_array(VdnApiJsonContentTypeSerializer::MIME_TYPE, $allContentTypes, true)) {
224+
$vdnApiJsonSerializerInit = $this->builder->methodCall(
225+
$xmlSerializerInit ?? $formEncodedSerializerInit ?? $jsonSerializerInit ?? $initialStatement,
226+
'add',
227+
[
228+
$this->builder->new('VdnApiJsonContentTypeSerializer'),
229+
]
230+
);
231+
}
232+
222233
$registerBodySerializerClosureStatements[] = $this
223234
->builder
224-
->return($xmlSerializerInit ?? $formEncodedSerializerInit ?? $jsonSerializerInit ?? $initialStatement);
235+
->return($vdnApiJsonSerializerInit ?? $xmlSerializerInit ?? $formEncodedSerializerInit ?? $jsonSerializerInit ?? $initialStatement);
225236

226237
return $this->builder->closure(
227238
$registerBodySerializerClosureStatements,

src/Input/Specification.php

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use DoclerLabs\ApiClientGenerator\Entity\OperationCollection;
99
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\FormUrlencodedContentTypeSerializer;
1010
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\JsonContentTypeSerializer;
11+
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\VdnApiJsonContentTypeSerializer;
1112
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\XmlContentTypeSerializer;
1213

1314
class Specification
@@ -82,6 +83,7 @@ public function getAllContentTypes(): array
8283
XmlContentTypeSerializer::MIME_TYPE => false,
8384
FormUrlencodedContentTypeSerializer::MIME_TYPE => false,
8485
JsonContentTypeSerializer::MIME_TYPE => false,
86+
VdnApiJsonContentTypeSerializer::MIME_TYPE => false,
8587
];
8688

8789
/** @var Operation $operation */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType;
4+
5+
use DoclerLabs\ApiClientGenerator\Output\Copy\Schema\SerializableInterface;
6+
use Psr\Http\Message\StreamInterface;
7+
8+
abstract class AbstractJsonContentTypeSerializer implements ContentTypeSerializerInterface
9+
{
10+
private const JSON_DEPTH = 512;
11+
private const JSON_OPTIONS = JSON_BIGINT_AS_STRING | JSON_PRESERVE_ZERO_FRACTION | JSON_UNESCAPED_UNICODE;
12+
13+
/**
14+
* @throws SerializeException
15+
*/
16+
public function encode(SerializableInterface $body): string
17+
{
18+
$encodedData = json_encode($body->toArray(), self::JSON_OPTIONS);
19+
20+
$lastErrorCode = json_last_error();
21+
if ($lastErrorCode === JSON_ERROR_NONE && $encodedData !== false) {
22+
return $encodedData;
23+
}
24+
25+
throw new SerializeException('JSON encode error: ' . $this->getErrorMessage($lastErrorCode));
26+
}
27+
28+
/**
29+
* @throws SerializeException
30+
*/
31+
public function decode(StreamInterface $body): array
32+
{
33+
$body->rewind();
34+
35+
// According to RFC7159 a JSON value MUST be an object, array, number, string,
36+
// or one of the following three literal names: false, null, true.
37+
$result = json_decode($body->getContents(), true, self::JSON_DEPTH, self::JSON_OPTIONS);
38+
39+
$lastErrorCode = json_last_error();
40+
if ($lastErrorCode === JSON_ERROR_NONE) {
41+
if (!is_array($result)) {
42+
$result = [
43+
ContentTypeSerializerInterface::LITERAL_VALUE_KEY => $result,
44+
];
45+
}
46+
47+
return $result;
48+
}
49+
50+
throw new SerializeException('JSON decode error: ' . $this->getErrorMessage($lastErrorCode));
51+
}
52+
53+
private function getErrorMessage(int $errorCode): string
54+
{
55+
$errorMessages = [
56+
JSON_ERROR_NONE => 'No errors',
57+
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
58+
JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch',
59+
JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
60+
JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
61+
JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded',
62+
JSON_ERROR_RECURSION => 'Recursive reference was found',
63+
JSON_ERROR_INF_OR_NAN => 'NaN or Inf was found',
64+
JSON_ERROR_UNSUPPORTED_TYPE => 'Unsupported type was found',
65+
];
66+
67+
return $errorMessages[$errorCode] ?? 'Unknown error';
68+
}
69+
}

src/Output/Copy/Serializer/ContentType/JsonContentTypeSerializer.php

+2-61
Original file line numberDiff line numberDiff line change
@@ -2,71 +2,12 @@
22

33
namespace DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType;
44

5-
use DoclerLabs\ApiClientGenerator\Output\Copy\Schema\SerializableInterface;
6-
use Psr\Http\Message\StreamInterface;
7-
8-
class JsonContentTypeSerializer implements ContentTypeSerializerInterface
5+
class JsonContentTypeSerializer extends AbstractJsonContentTypeSerializer
96
{
10-
const MIME_TYPE = 'application/json';
11-
const JSON_DEPTH = 512;
12-
const JSON_OPTIONS = JSON_BIGINT_AS_STRING | JSON_PRESERVE_ZERO_FRACTION | JSON_UNESCAPED_UNICODE;
13-
14-
public function encode(SerializableInterface $body): string
15-
{
16-
$encodedData = json_encode($body->toArray(), self::JSON_OPTIONS);
17-
18-
$lastErrorCode = json_last_error();
19-
if ($lastErrorCode === JSON_ERROR_NONE && $encodedData !== false) {
20-
return $encodedData;
21-
}
22-
23-
throw new SerializeException('JSON encode error: ' . $this->getErrorMessage($lastErrorCode));
24-
}
25-
26-
/**
27-
* @throws SerializeException
28-
*/
29-
public function decode(StreamInterface $body): array
30-
{
31-
$body->rewind();
32-
33-
// According to RFC7159 a JSON value MUST be an object, array, number, string,
34-
// or one of the following three literal names: false, null, true.
35-
$result = json_decode($body->getContents(), true, self::JSON_DEPTH, self::JSON_OPTIONS);
36-
37-
$lastErrorCode = json_last_error();
38-
if ($lastErrorCode === JSON_ERROR_NONE) {
39-
if (!is_array($result)) {
40-
$result = [
41-
ContentTypeSerializerInterface::LITERAL_VALUE_KEY => $result,
42-
];
43-
}
44-
45-
return $result;
46-
}
47-
48-
throw new SerializeException('JSON decode error: ' . $this->getErrorMessage($lastErrorCode));
49-
}
7+
public const MIME_TYPE = 'application/json';
508

519
public function getMimeType(): string
5210
{
5311
return self::MIME_TYPE;
5412
}
55-
56-
private function getErrorMessage(int $errorCode): string
57-
{
58-
$errorMessages = [
59-
JSON_ERROR_NONE => 'No errors',
60-
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
61-
JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch',
62-
JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
63-
JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
64-
JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded',
65-
JSON_ERROR_RECURSION => 'Recursive reference was found',
66-
JSON_ERROR_INF_OR_NAN => 'NaN or Inf was found',
67-
JSON_ERROR_UNSUPPORTED_TYPE => 'Unsupported type was found',
68-
];
69-
70-
return $errorMessages[$errorCode] ?? 'Unknown error';
71-
}
7213
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType;
4+
5+
class VdnApiJsonContentTypeSerializer extends AbstractJsonContentTypeSerializer
6+
{
7+
public const MIME_TYPE = 'application/vnd.api+json';
8+
9+
public function getMimeType(): string
10+
{
11+
return self::MIME_TYPE;
12+
}
13+
}

0 commit comments

Comments
 (0)