Okhttp + Gson を使ったJavaによるWebAPI入門
大学の授業の副手でJavaでWebAPIを使ったプログラムについてまとめることになったのでここにまとめます。
使用するライブラリ
JavaでHTTP通信だったりJSONを扱うのに一から自分で書くのって結構つらいですよね。
またエラーハンドリングとかしっかりやらないととても使えるものにはならないと思います。
よって今回はライブラリを使います。
※ 勉強するのにライブラリ使って良いのかよって思う人もいると思いますが、今回はサクッと使えるようなサンプル用意してくれっていうオーダーだったのでライブラリは使用します。
使用するWebAPI
Livedoor Weather Web Service
Livedoorが提供している天気予報APIです。
てきとうに選びました。まぁ認証は無しのAPIならなんでも良かったです。
HTTP通信
通信部分はOkhttpを使います。
HttpUrl
後述の Request
インスタンスを作成するときにURLを指定するんですが、単純に文字列を渡してもいんですがUrlを作成するための HttpUrl
クラスも存在します。
こちらはいろんなエンドポイント用に文字列を用意しておいたり、パラメータの指定を簡単に書けるようにしてくれます。
作成するには HttpUrl.Builder
クラスが存在するので以下のように作成していきます。
HttpUrl.Builder builder = HttpUrl.Builder() .scheme(SCHEME) .host(HOST) .addPathSegment(FORECAST) .addPathSegment(WEB_SERVICE) .addPathSegment(JSON) .addPathSegment(ROOT);
上記で作成したURLは SCHEME://HOST/FORECAST/WEB_SERVICE/JSON/ROOT
になります。
またパラメータを指定するのも簡単で以下のように書きます。
builder.addQueryParameter("city", "400040");
これによって今回使用するURLが作成できました。
SCHEME://HOST/FORECAST/WEB_SERVICE/JSON/ROOT?city=400040
Request
通信するときは Request
インスタンスを作り OkHttpClient#newCall(Request request)
を使って Call
インスタンスを作ります。
通信方法には同期通信と非同期通信があり、同期通信は Call#execute()
を、非同期通信は Call#enqueue(Callback callback)
を使います。
また、 Request
を作るときにHTTPメソッドを指定して作成します。
今回はGETメソッドとPOSTメソッドについて説明します。
GET
Request.Builder
にURL渡して Request.Builder#get()
を叩くだけ。
まあ Request.Builder
のコンストラクタの実装を見るとわかると思いますが、デフォルトはGETメソッドが指定されてるので get()
メソッド叩かなくても良いかも。
Request request = new Request.Builder()
.url(builder.build())
.get()
.build();
※ builder
はHttpUrlの項目で作成したもの。
POST
POSTメソッドは以下のように使用します。
JSONオブジェクトをつけてPOSTの Request
を作成してみます。
MediaType jsonMedia = MediaType.parse("application/json; charset=utf-8"); Request request = new Request.Builder() .url(buildStateUrl()) .post(RequestBody.create(jsonMedia, "{\"key\": \"value\"}")) .build();
だいたいこんな感じです。他にもいろいろあるので気になる人は自分で調べてみてください。
通信
あと残りは仕上げです。
先程述べた通り通信には2種類あり、同期通信と非同期通信です。
また、通信するには Call
オブジェクトが必要です。
これまでに作ってきたRequestから以下のように作成します。
OkHttpClient client = new OkHttpClient();
Call call = client.newCall(request);
同期通信
特に難しいことはありません。 Call#execute()
を叩くだけです。
Response response = client.newCall(request).execute();
非同期通信
こちらもそんなに難しいことはありません。非同期通信なのでCallbackが必要になるだけです。
client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // Error } @Override public void onResponse(Call call, Response response) { // Success } });
どちらも通信が終わったあとに Response
オブジェクトが返ってくるのでそこから結果を取得します。
今回使用するAPIではbody部分にJSONオブジェクトが返ってくるので以下の用に受け取ります。
String result = response.body().string();
これで通信部分は終了です。
次はWebAPIから取得したJSONオブジェクトGsonを使って実際に使えるようにします。
Gson
それでは取得できたJSONをJavaオブジェクトに変換して使えるようにしましょう。
まずJavaオブジェクトに変換するにはそれに対応するクラスを定義しないといけません。
例として以下のようなJSONがあるとします。
{ "id": 321, "name": "nshiba", "birth": { "country": "Japan", "day": "1990-01-01" }, "friends": [ 123, 234, 345, 456 ] }
これをJavaオブジェクトに変換しようと思ったら、全体用のクラスと birth
用のクラス、2つのクラスが必要です。
public class UserEntity { @SerializedName("id") private int id; @SerializedName("name") private String name; @SerializedName("birth") private BirthEntity birth; @SerializedName("friends") private List<Integer> friendList; public int getId() { return id; } public String getName() { return name; } public BirthEntity getBirth() { return birth; } public List<Integer> getFriendList() { return friendList; } }
public class BirthEntity { @SerializedName("country") private String country; @SerializedName("day") private String day; public String getCountry() { return country; } public String getDay() { return day; } }
これでクラスの宣言はできたので以下のようにGsonを使って変換します。
UserEntity userEntity = gson.fromJson(result, UserEntity.class);
まとめ
これで一通り入門できたのかもしれないです。
一応こんな感じで実装していけば問題ないかな、思う範囲でサクッと作ったのですが問題がでそうな部分があったら教えてもらえると幸いです。
質問などあればコメントでお願いします。
また、今回作成したサンプルは公開していますので、コードはそちらの方が参考にできると思います。