swaggerでAPIドキュメントを作ってみる

swaggerって？
http://swagger.io/
簡単にAPIドキュメントを作成してくれる便利なツールという認識になりました。

実際に既存のコードから簡単にドキュメントを作成してみました。

サンプルはMaven + JAX-RSです。
swaggerがサポートしているのは、SpringMvc & JAX-RSで書かれたAPIとのこと

こんなAPIがあるとします
APIをJAX-RSで定義しています。

``` xml:pom.xml
    <dependency>
      <groupId>javax.ws.rs</groupId>
      <artifactId>javax.ws.rs-api</artifactId>
      <version>2.0.1</version>
    </dependency>
```


``` java:ApiSample.java
@Path("/sample")
public class ApiSample {

    @GET
    @Path("user.json")
    public User getUser(
            @PathParam("name")
            String name) {
    	User user = new User(name);
    	return user;
    };
}
```

``` java:User.java
public class User {

    public String name;
    
    public int age = 20;
    
    public User(name) {
    	this.name = name;
    }
}
```

このAPIの仕様書をswaggerライブラリを使って作ります。

# 1. swaggerライブラリを追加する

``` xml:pom.xml
    <dependency>
      <groupId>io.swagger</groupId>
      <artifactId>swagger-jersey2-jaxrs</artifactId>
      <scope>compile</scope>
      <version>1.5.0</version>
    </dependency>
```

# 2. swagger annotation を追加する
``` java:ApiSample.java

@Path("/sample")
@Api(tags = {"/sample"}) // 追加(必須)
public class ApiSample {

    @GET
    @Path("user.json")
    @ApiOperation(value = "Userを返します.")  // 追加(必須)
    public User getUser(
    		@ApiParam(value = "ユーザー名", required = true)  // 追加(任意)
    		@PathParam("name")
    		String name) {
    	User user = new User(name);
    	return user;
    };
```

# 3. 必要なファイルを追加する
https://github.com/kongchen/swagger-maven-example/tree/master/templates
上記のファイル4つを全て
プロジェクト内の任意の同一のフォルダに配置します。
※何に必要なのかよくわかりませんでした。。。


# 4.さらにドキュメントビルド用にライブラリと設定値を追加する

``` xml:pom.xml

	<build>
		<plugins>
			<!-- swagger -->
			<plugin>
				<groupId>com.github.kongchen</groupId>
				<artifactId>swagger-maven-plugin</artifactId>
				<version>3.1.0</version>
				<configuration>
					<apiSources>
						<apiSource>
							<springmvc>false</springmvc>
							<locations>swagger_sample.swagger_pom</locations>
							<info>
								<title>Sample Api</title>
								<version>1.0.0</version>
								<description>This is a specification for Sample API</description>
							</info>
							<templatePath>${project.basedir}/src/main/strapdown.html.hbs</templatePath>
							<outputPath>${project.basedir}/target/document.html</outputPath>
							<swaggerDirectory>${project.basedir}/target/swagger-ui</swaggerDirectory>
						</apiSource>
					</apiSources>
				</configuration>
				<executions>
					<execution>
						<phase>compile</phase>
						<goals>
							<goal>generate</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.1.1</version>
			</plugin>
		</plugins>
	</build>
```

↑ここで
<templatePath>${project.basedir}/src/main/strapdown.html.hbs</templatePath>
↑の値にひとつ前の手順で配置してもらったファイルのひとつ「strapdown.html.hbs」のパスを
指定します。


_どのタグが何を意味するかはここを見るといいです。_
https://github.com/kongchen/swagger-maven-plugin

# 5.コマンドプロンプトから下記コマンド実行
``` linux
$ mvn compile
```

するとプロジェクト直下のtargetに
「document.html」
「swagger-ui」
が生成されました。
（```<outputPath>```、```<swaggerDirectory>```に指定した場所です）

document.htmlを開いてみるとかっこいい感じのドキュメントが出来ています。

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

![document.png](https://qiita-image-store.s3.amazonaws.com/0/74613/b9cba345-5903-79fe-4f57-1f03fe9b9930.png)

  
  
# さらにもうひとつ
swagger-uiですが、その中に「swagger.json」が入っています。
これはswagger-uiというアプリにかませることで、使えます。

swagger-uiはこちら
https://github.com/swagger-api/swagger-ui

まるごとダウンロードして、
swagger-ui/dist/index.htmlを開き、

赤枠のところにswagger.jsonのパスを入れるだけです。

![ui_1.PNG](https://qiita-image-store.s3.amazonaws.com/0/74613/8d6058fb-3c86-bfba-b1dd-010bcd21e799.png)



が、ここで躓きました。
これはローカル環境でやると開けないみたいです。
調べてみると、
「ローカルにサーバーを立ててそこにアクセスすればいい」という記述を見た。

tomcatのwebappsにdistごとコピー。
swagger.jsonもdistにコピー

http://localhost:8080/dist/
にアクセスし、swagger.jsonのパス
http://localhost:8080/dist/swagger.json
を赤枠に入れると・・・
無事に見れました。

![ui_2.PNG](https://qiita-image-store.s3.amazonaws.com/0/74613/c8580281-e5aa-cd67-e624-95f27079cc6b.png)


かっこいいかんじですね。

**ここでパラメータを渡して、レスポンスをみる。ということもできるみたいです。**


## **<Font color="red">※注意</font>**

おそらくjsonをうまく生成できないからなのですが、
下記のようにクラス内に同じクラスをもっていると生成したswagger.jsonがおかしくなり、

_fetching resource list: http://localhost:8080/dist/swagger.json; Please wait._
の表示のまま止まってしまいます。

``` java:User.java
public class User {

    public String name;
    
    public List<User> friends; // コレ！
}
```

どうやらswagger.json内のこの状態がいけないらしい
※Listなのにarrayになっている！そっちではないです。それは正常らしいです。

```
    "User" : {
      "type" : "object",
      "properties" : {
        "name" : {
          "type" : "string"
        },
        "friends" : {
          "type" : "array"
        }
      }
    }
```

なにがいけないかというと
friendsに指定されていないことです。
なので無理やり手動で直すと読み込めるようになりました。

```
    "User" : {
      "type" : "object",
      "properties" : {
        "name" : {
          "type" : "string"
        },
        "friends" : {
          "type" : "array"

          ↓これ
          "items" : {
            "$ref" : "#/definitions/User"
          }

        }
      }
    }
```

# ほかにも
ここでは最小限の設定しかしませんでしたが

他にもpom.xmlに設定値を追加したり、
→https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md

ApiSample.javaに設定を追加したり、
→https://github.com/swagger-api/swagger-core/wiki/Annotations
ex.@ApiOperationのoptionalなパラメータを付与する

User.javaにも使えたり
→https://github.com/swagger-api/swagger-core/wiki/Annotations
ex.@ApiModelProperty
ex.Jackson( http://www.codehaus.org/ )の@JsonIgnoreがswaggerにも使える(無視される)

良いドキュメントが出来そうです。

おしまい