nelmio/NelmioApiDocBundleでスキーマの定義するのは結構だるいことが多いです。
@Model
アノテーションとか使って簡単に定義することもできますが、最終的にJSONになるのにクラスにマッピングしてレスポンス返すのが微妙だと感じる場合もあると思います。
そこで、JsonSchema活用できないかなと思って調べたらスキーマ定義に利用することができました。
今回はその方法を書いてきます。
サンプルコードについて
今回のサンプルコードはこちらになります。
polidog/sf-nelmio-doc-json-sample
Schemaファイルを用意する
まずはスキーマファイルを作らないと話にならないので、スキーマファイルを用意します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// public/json_schema/new.json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "new projects",
"description": "Schema of post data for creating a new project",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 10,
"maxLength": 255
}
},
"required": ["name"]
}
|
nelmio_api_doc.yamlでdefinitionsの設定をする
nelmio_api_docでjsonスキーマを利用するにはdefinitionsの設定が必要になります。
1
2
3
4
5
6
7
8
9
10
11
12
|
nelmio_api_doc:
documentation:
info:
title: Smaple API
description: This is an awesome app!
version: 1.0.0
definitions:
new_project:
$ref: 'http://127.0.0.1:8000/json_schema/new.json'
areas: # to filter documented areas
path_patterns:
- ^/api(?!/doc$) # Accepts routes under /api except /api/doc
|
ここで問題になるのが http://127.0.0.1:8000
で指定してしまっていること。
その場合は.envでURLを設定しておくと良いかと思います。
1
2
3
|
definitions:
new_project:
$ref: '%env(API_DOC_HOST)%/json_schema/new.json'
|
コントローラにNelmioApiDoc用の設定を記述する
@SWG\Parameter
アノテーションの中に記述されている@SWG\Schema
に、nelmio_api_doc.yamlで指定したdefinitionsのnew_project
を指定します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
<?php
namespace App\Controller\Api;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Swagger\Annotations as SWG;
/**
* @Request("/api/new", methods={"POST"})
*/
class NewController
{
/**
* @SWG\Parameter(
* name="new",
* in="body",
* schema=@SWG\Schema(ref="#definitions/new_project")
* )
*
* @SWG\Response(
* response=201,
* description="create resource."
* )
*/
public function __invoke(Request $request)
{
$name = $request->request->get('name');
// TODO add project code.
return new JsonResponse(['status' => 'ok']);
}
}
|
ドキュメントページにアクセスする
ドキュメントページにアクセスしてみると、jsonSchemaの内容が反映されています。
デフォルトだとhttp://127.0.0.1:8000/api/doc
にアクセスすると以下のように表示されます。
Parametersの部分にJSONスキーマの情報が反映されています。
バリデーションを行う(おまけ)
JSONSchemaを定義したらバリデーションをしたくなると思います。
そんなときに利用できるのが ptyhard/JsonSchemaBundleです。
ドキュメントには記載がないのですが、@SchemaFile
というアノテーションがあります。
このアノテーションにファイルのパスを指定することにより、リクエストまたはレスポンス時にJsonSchemaValidationを実行します。
まずは、composer requireします。
1
|
$ composer req ptyhard/json-schema-bundle
|
次に config/ptyhard_json_schema.yaml
を用意します。
json_schemaを配置しているディレクトリを指定してください。
1
2
|
ptyhard_json_schema:
json_file_directory: '%kernel.project_dir%/public/json_schema'
|
最後にコントローラに @SchemaFile
のアノテーションを定義します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
<?php
namespace App\Controller\Api;
use Ptyhard\JsonSchemaBundle\Annotations\SchemaFile;
use Symfony\Component\HttpFoundation\JsonResponse;
use Swagger\Annotations as SWG;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/api/new", methods={"POST"})
*/
class NewController
{
/**
* @SWG\Parameter(
* name="new",
* in="body",
* schema=@SWG\Schema(ref="#definitions/new_project")
* )
*
* @SWG\Response(
* response=201,
* description="create resource."
* )
*
* @SWG\Tag(name="project")
* @SchemaFile("new.json", type={"request"})
*/
public function __invoke(Request $request)
{
$name = $request->request->get('name');
// TODO add project code.
return new JsonResponse(['status' => 'ok']);
}
}
|
これで、設定は完了です。
/api/doc
から試しにバリデーションが実行されるか確認してみましょう。
キャプチャ画像で成功するリクエストと、バリデーションエラーになる実行結果を用意しました。
最後に
NelmioApiDocBundleでJsonSchemaを活用するのはフロントエンドとの親和性もあがるので良いアプローチだと思います。
ぜひ試してみてください。
そして、ptyhard/JsonSchemaBundleも使い勝手が良いのでぜひ使ってみてください。