Arbeiten Sie mit JSON RPC in Symfony 4


Hallo allerseits, heute werden wir darüber sprechen, wie Sie Freunde Symfony 4, JSON RPC und OpenAPI 3 finden können.


Dieser Artikel ist nicht für Anfänger gedacht. Sie sollten bereits verstehen, wie man mit Symfony, Depedency Injection und anderen "beängstigenden" Dingen arbeitet.


Sehen wir uns heute eine bestimmte Implementierung von JSON RPC an.


Implementierungen


Es gibt viele JSON RPC-Implementierungen für Symfony, insbesondere:



Wir werden in diesem Artikel über Letzteres sprechen. Diese Bibliothek hat mehrere Vorteile, die meine Wahl bestimmt haben.


Es wurde ohne Bindung an ein Framework ( yoanm / php-jsonrpc-server-sdk ) entwickelt, es gibt ein Bundle für Symfony, es enthält mehrere zusätzliche Pakete, mit denen Sie eingehende Daten überprüfen, automatische Dokumentation, Ereignisse und Schnittstellen hinzufügen können, um die Arbeit ohne Neudefinition zu ergänzen.


Installation


Installieren Sie zunächst symfony / skeleton.


$ composer create-project symfony/skeleton jsonrpc 

Gehen Sie zum Projektordner.


 $ cd jsonrpc 

Und installieren Sie die erforderliche Bibliothek.


 $ composer require yoanm/symfony-jsonrpc-http-server 

Anpassbar.


 // config/bundles.php return [ ... Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], Yoanm\SymfonyJsonRpcHttpServer\JsonRpcHttpServerBundle::class => ['all' => true], ... ]; 

 # config/routes.yaml json-rpc-endpoint: resource: '@JsonRpcHttpServerBundle/Resources/config/routing/endpoint.xml' 

 # config/packages/json_rpc.yaml json_rpc_http_server: ~ 

Fügen Sie einen Dienst hinzu, der alle unsere Methoden speichert.


 // src/MappingCollector.php <?php namespace App; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodAwareInterface; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodInterface; class MappingCollector implements JsonRpcMethodAwareInterface { /** @var JsonRpcMethodInterface[] */ private $mappingList = []; public function addJsonRpcMethod(string $methodName, JsonRpcMethodInterface $method): void { $this->mappingList[$methodName] = $method; } /** * @return JsonRpcMethodInterface[] */ public function getMappingList() : array { return $this->mappingList; } } 

Und fügen Sie den Dienst zu services.yaml hinzu.


 # config/services.yaml services: ... mapping_aware_service: class: App\MappingCollector tags: ['json_rpc_http_server.method_aware'] ... 

Methodenimplementierung


RPC-JSON-Methoden werden als reguläre Dienste in die Datei services.yaml aufgenommen. Wir implementieren zuerst die Ping-Methode selbst.


 // src/Method/PingMethod.php <?php namespace App\Method; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodInterface; class PingMethod implements JsonRpcMethodInterface { public function apply(array $paramList = null) { return 'pong'; } } 

Und als Service hinzufügen.


 # config/services.yaml services: ... App\Method\PingMethod: public: false tags: [{ method: 'ping', name: 'json_rpc_http_server.jsonrpc_method' }] ... 

Wir starten den eingebauten Webserver Symfony.


 $ symfony serve 

Wir versuchen einen Anruf zu tätigen.


 $ curl 'http://127.0.0.1:8000/json-rpc' --data-binary '[{ "jsonrpc":"2.0","method":"ping","params":[],"id" : 1 }]' 

 [ { "jsonrpc": "2.0", "id": 1, "result": "pong" } ] 

Jetzt implementieren wir die Methode, die die Parameter empfängt. Wir werden die Eingabedaten als Antwort zurückgeben.


 // src/Method/ParamsMethod.php <?php namespace App\Method; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodInterface; class ParamsMethod implements JsonRpcMethodInterface { public function apply(array $paramList = null) { return $paramList; } } 

 # config/services.yaml services: ... App\Method\ParamsMethod: public: false tags: [{ method: 'params', name: 'json_rpc_http_server.jsonrpc_method' }] ... 

Ich versuche anzurufen.


 $ curl 'http://127.0.0.1:8000/json-rpc' --data-binary '[{ "jsonrpc":"2.0","method":"params","params":{"name":"John","age":21},"id" : 1 }]' 

 [ { "jsonrpc": "2.0", "id": 1, "result": { "name": "John", "age": 21 } } ] 

Validierung der Methodeneingabe


Wenn eine automatische Überprüfung der Daten am Eingang der Methode erforderlich ist, gibt es in diesem Fall das Paket yoanm / symfony-jsonrpc-params-validator .


 $ composer require yoanm/symfony-jsonrpc-params-validator 

Verbinden Sie das Bundle.


 // config/bundles.php return [ ... Yoanm\SymfonyJsonRpcParamsValidator\JsonRpcParamsValidatorBundle::class => ['all' => true], ... ]; 

Methoden, die die Eingabe überprüfen müssen, müssen die Schnittstelle Yoanm \ JsonRpcParamsSymfonyValidator \ Domain \ MethodWithValidatedParamsInterface implementieren . Lassen Sie uns die ParamsMethod- Klasse ein wenig ändern.


 // src/Method/ParamsMethod.php <?php namespace App\Method; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Choice; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\Optional; use Symfony\Component\Validator\Constraints\Positive; use Symfony\Component\Validator\Constraints\Required; use Yoanm\JsonRpcParamsSymfonyValidator\Domain\MethodWithValidatedParamsInterface; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodInterface; class ParamsMethod implements JsonRpcMethodInterface, MethodWithValidatedParamsInterface { public function apply(array $paramList = null) { return $paramList; } public function getParamsConstraint() : Constraint { return new Collection(['fields' => [ 'name' => new Required([ new Length(['min' => 1, 'max' => 32]) ]), 'age' => new Required([ new Positive() ]), 'sex' => new Optional([ new Choice(['f', 'm']) ]), ]]); } } 

Wenn wir nun die Anfrage mit leeren Parametern oder mit Fehlern ausführen, erhalten wir die entsprechenden Fehler als Antwort.


 $ curl 'http://127.0.0.1:8000/json-rpc' --data-binary '[{"jsonrpc":"2.0","method":"params","params":[],"id" : 1 }]' 

 [ { "jsonrpc": "2.0", "id": 1, "error": { "code": -32602, "message": "Invalid params", "data": { "violations": [ { "path": "[name]", "message": "This field is missing.", "code": "2fa2158c-2a7f-484b-98aa-975522539ff8" }, { "path": "[age]", "message": "This field is missing.", "code": "2fa2158c-2a7f-484b-98aa-975522539ff8" } ] } } } ] 

 $ curl 'http://127.0.0.1:8000/json-rpc' --data-binary '[{"jsonrpc":"2.0","method":"params","params":{"name":"John","age":-1},"id" : 1 }]' 

 [ { "jsonrpc": "2.0", "id": 1, "error": { "code": -32602, "message": "Invalid params", "data": { "violations": [ { "path": "[age]", "message": "This value should be positive.", "code": "778b7ae0-84d3-481a-9dec-35fdb64b1d78" } ] } } } 

 $ curl 'http://127.0.0.1:8000/json-rpc' --data-binary '[{ "jsonrpc":"2.0","method":"params","params":{"name":"John","age":21,"sex":"u"},"id" : 1 }]' 

 [ { "jsonrpc": "2.0", "id": 1, "error": { "code": -32602, "message": "Invalid params", "data": { "violations": [ { "path": "[sex]", "message": "The value you selected is not a valid choice.", "code": "8e179f1b-97aa-4560-a02f-2a8b42e49df7" } ] } } } ] 

Automatische Dokumentation


Installieren Sie ein zusätzliches Paket.


 composer require yoanm/symfony-jsonrpc-http-server-doc 

Wir konfigurieren das Bundle.


 // config/bundles.php return [ ... Yoanm\SymfonyJsonRpcHttpServerDoc\JsonRpcHttpServerDocBundle::class => ['all' => true], ... ]; 

 # config/routes.yaml ... json-rpc-endpoint-doc: resource: '@JsonRpcHttpServerDocBundle/Resources/config/routing/endpoint.xml' 

 # config/packages/json_rpc.yaml ... json_rpc_http_server_doc: ~ 

Jetzt können Sie die Dokumentation im JSON-Format erhalten.


 $ curl 'http://127.0.0.1:8000/doc' 

Die Antwort
 { "methods": [ { "identifier": "Params", "name": "params" }, { "identifier": "Ping", "name": "ping" } ], "errors": [ { "id": "ParseError-32700", "title": "Parse error", "type": "object", "properties": { "code": -32700 } }, { "id": "InvalidRequest-32600", "title": "Invalid request", "type": "object", "properties": { "code": -32600 } }, { "id": "MethodNotFound-32601", "title": "Method not found", "type": "object", "properties": { "code": -32601 } }, { "id": "ParamsValidationsError-32602", "title": "Params validations error", "type": "object", "properties": { "code": -32602, "data": { "type": "object", "nullable": true, "required": true, "siblings": { "violations": { "type": "array", "nullable": true, "required": false } } } } }, { "id": "InternalError-32603", "title": "Internal error", "type": "object", "properties": { "code": -32603, "data": { "type": "object", "nullable": true, "required": false, "siblings": { "previous": { "description": "Previous error message", "type": "string", "nullable": true, "required": false } } } } } ], "http": { "host": "127.0.0.1:8000" } } 

Aber wie so? Und wo ist die Beschreibung der Eingabeparameter? Fügen Sie dazu ein weiteres Bundle yoanm / symfony-jsonrpc-params-sf-Constraints-Doc ein .


 $ composer require yoanm/symfony-jsonrpc-params-sf-constraints-doc 

 // config/bundles.php return [ ... Yoanm\SymfonyJsonRpcParamsSfConstraintsDoc\JsonRpcParamsSfConstraintsDocBundle::class => ['all' => true], ... ]; 

Wenn wir jetzt eine Anfrage stellen, erhalten wir bereits JSON-Methoden mit Parametern.


 $ curl 'http://127.0.0.1:8000/doc' 

Die Antwort
 { "methods": [ { "identifier": "Params", "name": "params", "params": { "type": "object", "nullable": false, "required": true, "siblings": { "name": { "type": "string", "nullable": true, "required": true, "minLength": 1, "maxLength": 32 }, "age": { "type": "string", "nullable": true, "required": true }, "sex": { "type": "string", "nullable": true, "required": false, "allowedValues": [ "f", "m" ] } } } }, { "identifier": "Ping", "name": "ping" } ], "errors": [ { "id": "ParseError-32700", "title": "Parse error", "type": "object", "properties": { "code": -32700 } }, { "id": "InvalidRequest-32600", "title": "Invalid request", "type": "object", "properties": { "code": -32600 } }, { "id": "MethodNotFound-32601", "title": "Method not found", "type": "object", "properties": { "code": -32601 } }, { "id": "ParamsValidationsError-32602", "title": "Params validations error", "type": "object", "properties": { "code": -32602, "data": { "type": "object", "nullable": true, "required": true, "siblings": { "violations": { "type": "array", "nullable": true, "required": false, "item_validation": { "type": "object", "nullable": true, "required": true, "siblings": { "path": { "type": "string", "nullable": true, "required": true, "example": "[key]" }, "message": { "type": "string", "nullable": true, "required": true }, "code": { "type": "string", "nullable": true, "required": false } } } } } } } }, { "id": "InternalError-32603", "title": "Internal error", "type": "object", "properties": { "code": -32603, "data": { "type": "object", "nullable": true, "required": false, "siblings": { "previous": { "description": "Previous error message", "type": "string", "nullable": true, "required": false } } } } } ], "http": { "host": "127.0.0.1:8000" } } 

Openapi 3


Damit die JSON-Dokumentation mit dem OpenAPI 3-Standard kompatibel ist, müssen Sie yoanm / symfony-jsonrpc-http-server-openapi-doc installieren.


 $ composer require yoanm/symfony-jsonrpc-http-server-openapi-doc 

Anpassbar.


 // config/bundles.php return [ ... Yoanm\SymfonyJsonRpcHttpServerOpenAPIDoc\JsonRpcHttpServerOpenAPIDocBundle::class => ['all' => true], ... ]; 

Nach einer neuen Anfrage erhalten wir eine JSON-Dokumentation im OpenApi 3-Format.


 $ curl 'http://127.0.0.1:8000/doc/openapi.json' 

Die Antwort
 { "openapi": "3.0.0", "servers": [ { "url": "http:\/\/127.0.0.1:8000" } ], "paths": { "\/Params\/..\/json-rpc": { "post": { "summary": "\"params\" json-rpc method", "operationId": "Params", "requestBody": { "required": true, "content": { "application\/json": { "schema": { "allOf": [ { "type": "object", "required": [ "jsonrpc", "method" ], "properties": { "id": { "example": "req_id", "oneOf": [ { "type": "string" }, { "type": "number" } ] }, "jsonrpc": { "type": "string", "example": "2.0" }, "method": { "type": "string" }, "params": { "title": "Method parameters" } } }, { "type": "object", "required": [ "params" ], "properties": { "params": { "$ref": "#\/components\/schemas\/Method-Params-RequestParams" } } }, { "type": "object", "properties": { "method": { "example": "params" } } } ] } } } }, "responses": { "200": { "description": "JSON-RPC response", "content": { "application\/json": { "schema": { "allOf": [ { "type": "object", "required": [ "jsonrpc" ], "properties": { "id": { "example": "req_id", "oneOf": [ { "type": "string" }, { "type": "number" } ] }, "jsonrpc": { "type": "string", "example": "2.0" }, "result": { "title": "Result" }, "error": { "title": "Error" } } }, { "type": "object", "properties": { "result": { "description": "Method result" } } }, { "type": "object", "properties": { "error": { "oneOf": [ { "$ref": "#\/components\/schemas\/ServerError-ParseError-32700" }, { "$ref": "#\/components\/schemas\/ServerError-InvalidRequest-32600" }, { "$ref": "#\/components\/schemas\/ServerError-MethodNotFound-32601" }, { "$ref": "#\/components\/schemas\/ServerError-ParamsValidationsError-32602" }, { "$ref": "#\/components\/schemas\/ServerError-InternalError-32603" } ] } } } ] } } } } } } }, "\/Ping\/..\/json-rpc": { "post": { "summary": "\"ping\" json-rpc method", "operationId": "Ping", "requestBody": { "required": true, "content": { "application\/json": { "schema": { "allOf": [ { "type": "object", "required": [ "jsonrpc", "method" ], "properties": { "id": { "example": "req_id", "oneOf": [ { "type": "string" }, { "type": "number" } ] }, "jsonrpc": { "type": "string", "example": "2.0" }, "method": { "type": "string" }, "params": { "title": "Method parameters" } } }, { "type": "object", "properties": { "method": { "example": "ping" } } } ] } } } }, "responses": { "200": { "description": "JSON-RPC response", "content": { "application\/json": { "schema": { "allOf": [ { "type": "object", "required": [ "jsonrpc" ], "properties": { "id": { "example": "req_id", "oneOf": [ { "type": "string" }, { "type": "number" } ] }, "jsonrpc": { "type": "string", "example": "2.0" }, "result": { "title": "Result" }, "error": { "title": "Error" } } }, { "type": "object", "properties": { "result": { "description": "Method result" } } }, { "type": "object", "properties": { "error": { "oneOf": [ { "$ref": "#\/components\/schemas\/ServerError-ParseError-32700" }, { "$ref": "#\/components\/schemas\/ServerError-InvalidRequest-32600" }, { "$ref": "#\/components\/schemas\/ServerError-MethodNotFound-32601" }, { "$ref": "#\/components\/schemas\/ServerError-ParamsValidationsError-32602" }, { "$ref": "#\/components\/schemas\/ServerError-InternalError-32603" } ] } } } ] } } } } } } } }, "components": { "schemas": { "Method-Params-RequestParams": { "type": "object", "nullable": false, "required": [ "name", "age" ], "properties": { "name": { "type": "string", "nullable": true, "minLength": 1, "maxLength": 32 }, "age": { "type": "string", "nullable": true }, "sex": { "type": "string", "nullable": true, "enum": [ "f", "m" ] } } }, "ServerError-ParseError-32700": { "title": "Parse error", "allOf": [ { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "number" }, "message": { "type": "string" } } }, { "type": "object", "required": [ "code" ], "properties": { "code": { "example": -32700 } } } ] }, "ServerError-InvalidRequest-32600": { "title": "Invalid request", "allOf": [ { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "number" }, "message": { "type": "string" } } }, { "type": "object", "required": [ "code" ], "properties": { "code": { "example": -32600 } } } ] }, "ServerError-MethodNotFound-32601": { "title": "Method not found", "allOf": [ { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "number" }, "message": { "type": "string" } } }, { "type": "object", "required": [ "code" ], "properties": { "code": { "example": -32601 } } } ] }, "ServerError-ParamsValidationsError-32602": { "title": "Params validations error", "allOf": [ { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "number" }, "message": { "type": "string" } } }, { "type": "object", "required": [ "code", "data" ], "properties": { "code": { "example": -32602 }, "data": { "type": "object", "nullable": true, "properties": { "violations": { "type": "array", "nullable": true, "items": { "type": "object", "nullable": true, "required": [ "path", "message" ], "properties": { "path": { "type": "string", "nullable": true, "example": "[key]" }, "message": { "type": "string", "nullable": true }, "code": { "type": "string", "nullable": true } } } } } } } } ] }, "ServerError-InternalError-32603": { "title": "Internal error", "allOf": [ { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "number" }, "message": { "type": "string" } } }, { "type": "object", "required": [ "code" ], "properties": { "code": { "example": -32603 }, "data": { "type": "object", "nullable": true, "properties": { "previous": { "description": "Previous error message", "type": "string", "nullable": true } } } } } ] } } } } 

Dokumentation zur Methodenantwort


Es gibt keine reguläre Funktion (z. B. durch Implementierung einer Schnittstelle), mit der Sie der Dokumentation Methodenantworten hinzufügen können. Es besteht jedoch die Möglichkeit, durch Abonnieren von Ereignissen die erforderlichen Informationen selbst hinzuzufügen.


Fügen Sie einen Listener hinzu.


 # config/services.yaml services: ... App\Listener\MethodDocListener: tags: - name: 'kernel.event_listener' event: 'json_rpc_http_server_doc.method_doc_created' method: 'enhanceMethodDoc' - name: 'kernel.event_listener' event: 'json_rpc_http_server_openapi_doc.array_created' method: 'enhanceDoc' ... 

 // src/Listener/MethodDocListener.php <?php namespace App\Listener; use App\Domain\JsonRpcMethodWithDocInterface; use Yoanm\JsonRpcServerDoc\Domain\Model\ErrorDoc; use Yoanm\SymfonyJsonRpcHttpServerDoc\Event\MethodDocCreatedEvent; use Yoanm\SymfonyJsonRpcHttpServerOpenAPIDoc\Event\OpenAPIDocCreatedEvent; class MethodDocListener { public function enhanceMethodDoc(MethodDocCreatedEvent $event) : void { $method = $event->getMethod(); if ($method instanceof JsonRpcMethodWithDocInterface) { $doc = $event->getDoc(); $doc->setResultDoc($method->getDocResponse()); foreach ($method->getDocErrors() as $error) { if ($error instanceof ErrorDoc) { $doc->addCustomError($error); } } $doc->setDescription($method->getDocDescription()); $doc->addTag($method->getDocTag()); } } public function enhanceDoc(OpenAPIDocCreatedEvent $event) { $doc = $event->getOpenAPIDoc(); $doc['info'] = [ 'title' => 'Main title', 'version' => '1.0.0', 'description' => 'Main description' ]; $event->setOpenAPIDoc($doc); } } 

Um die Dokumentation von Methoden nicht direkt im Listener direkt zu beschreiben, erstellen wir eine Schnittstelle, die die Methoden selbst implementieren müssen.


 // src/Domain/JsonRpcMethodWithDocInterface.php <?php namespace App\Domain; use Yoanm\JsonRpcServerDoc\Domain\Model\ErrorDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\TypeDoc; interface JsonRpcMethodWithDocInterface { /** * @return TypeDoc */ public function getDocResponse(): TypeDoc; /** * @return ErrorDoc[] */ public function getDocErrors(): array; /** * @return string */ public function getDocDescription(): string; /** * @return string */ public function getDocTag(): string; } 

Fügen Sie nun eine neue Methode hinzu, die die erforderlichen Informationen enthält.


 // src/Method/UserMethod.php <?php namespace App\Method; use App\Domain\JsonRpcMethodWithDocInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Choice; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\Optional; use Symfony\Component\Validator\Constraints\Positive; use Symfony\Component\Validator\Constraints\Required; use Yoanm\JsonRpcParamsSymfonyValidator\Domain\MethodWithValidatedParamsInterface; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodInterface; use Yoanm\JsonRpcServerDoc\Domain\Model\ErrorDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\ArrayDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\NumberDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\ObjectDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\StringDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\TypeDoc; class UserMethod implements JsonRpcMethodInterface, MethodWithValidatedParamsInterface, JsonRpcMethodWithDocInterface { public function apply(array $paramList = null) { return [ 'name' => $paramList['name'], 'age' => $paramList['age'], 'sex' => $paramList['sex'] ?? null, ]; } public function getParamsConstraint() : Constraint { return new Collection(['fields' => [ 'name' => new Required([ new Length(['min' => 1, 'max' => 32]) ]), 'age' => new Required([ new Positive() ]), 'sex' => new Optional([ new Choice(['f', 'm']) ]), ]]); } public function getDocDescription(): string { return 'User method'; } public function getDocTag(): string { return 'main'; } public function getDocErrors(): array { return [new ErrorDoc('Error 1', 1)]; } public function getDocResponse(): TypeDoc { $response = new ObjectDoc(); $response->setNullable(false); $response->addSibling((new StringDoc()) ->setNullable(false) ->setDescription('Name of user') ->setName('name') ); $response->addSibling((new NumberDoc()) ->setNullable(false) ->setDescription('Age of user') ->setName('age') ); $response->addSibling((new StringDoc()) ->setNullable(true) ->setDescription('Sex of user') ->setName('sex') ); return $response; } } 

Vergessen Sie nicht, einen neuen Dienst zu registrieren.


 services: ... App\Method\UserMethod: public: false tags: [{ method: 'user', name: 'json_rpc_http_server.jsonrpc_method' }] ... 

Wenn wir jetzt eine neue Anfrage an /doc/openapi.json stellen , erhalten wir neue Daten.


 curl 'http://127.0.0.1:8000/doc/openapi.json' 

Die Antwort
 { "openapi": "3.0.0", "servers": [ { "url": "http:\/\/127.0.0.1:8000" } ], "paths": { ... "\/User\/..\/json-rpc": { "post": { "summary": "\"user\" json-rpc method", "description": "User method", "tags": [ "main" ], ... "responses": { "200": { "description": "JSON-RPC response", "content": { "application\/json": { "schema": { "allOf": [ ... { "type": "object", "properties": { "result": { "$ref": "#\/components\/schemas\/Method-User-Result" } } }, { "type": "object", "properties": { "error": { "oneOf": [ { "$ref": "#\/components\/schemas\/Error-Error11" }, ... ] } } } ] } } } } } } } }, "components": { "schemas": { ... "Method-User-Result": { "type": "object", "nullable": false, "properties": { "name": { "description": "Name of user", "type": "string", "nullable": false }, "age": { "description": "Age of user", "type": "number", "nullable": false }, "sex": { "description": "Sex of user", "type": "string", "nullable": true } } }, "Error-Error11": { "title": "Error 1", "allOf": [ { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "number" }, "message": { "type": "string" } } }, { "type": "object", "required": [ "code" ], "properties": { "code": { "example": 1 } } } ] }, ... } }, "info": { "title": "Main title", "version": "1.0.0", "description": "Main description" } } 

Visualisierung der JSON-Dokumentation


JSON ist cool, aber die Leute wollen normalerweise ein menschlicheres Ergebnis sehen. Die Datei /doc/openapi.json kann an externe Visualisierungsdienste wie Swagger Editor übergeben werden .



Auf Wunsch können Sie die Swagger-Benutzeroberfläche in unserem Projekt installieren. Wir werden das Paket harmbandstra / swagger-ui-bundle verwenden .


Für die korrekte Veröffentlichung von Ressourcen fügen wir mit composer.json Folgendes hinzu.


  "scripts": { "auto-scripts": { "cache:clear": "symfony-cmd", "assets:install %PUBLIC_DIR%": "symfony-cmd" }, "post-install-cmd": [ "HarmBandstra\\SwaggerUiBundle\\Composer\\ScriptHandler::linkAssets", "@auto-scripts" ], "post-update-cmd": [ "HarmBandstra\\SwaggerUiBundle\\Composer\\ScriptHandler::linkAssets", "@auto-scripts" ] }, 

Nachdem wir das Paket gelegt haben.


 $ composer require harmbandstra/swagger-ui-bundle 

Verbinden Sie das Bundle.


 // config/bundles.php <?php return [ // ... HarmBandstra\SwaggerUiBundle\HBSwaggerUiBundle::class => ['dev' => true] ]; 

 # config/routes.yaml _swagger-ui: resource: '@HBSwaggerUiBundle/Resources/config/routing.yml' prefix: /docs 

 # config/packages/hb_swagger_ui.yaml hb_swagger_ui: directory: "http://127.0.0.1:8000" files: - "/doc/openapi.json" 

Wenn wir nun dem Link http://127.0.0.1:8000/docs/ folgen , erhalten wir die Dokumentation in einer schönen Form.



Zusammenfassung


Als Ergebnis aller Manipulationen haben wir einen funktionierenden JSON-RPC erhalten, der auf Symfony 4 und einer automatischen Dokumentation von OpenAPI mit Visualisierung über die Swagger-Benutzeroberfläche basiert.


Danke an alle.

Source: https://habr.com/ru/post/de457750/


All Articles