はじめに
前回は楽天のAPIを使う準備と簡単なテストを行いました。今回はSpring-webのRestTemplateを使ってJavaから楽天ショッピングAPIを呼び出してみようと思います。
やったこと
実装はGithubで公開しています。 楽天のApplication IDやApplication Secret、Affiliate IDは前回の記事を参照してください。 商品検索APIの情報はこちらにあります。入力パラメータも出力パラメータも全部載ってます。RestTemplateで使うため、Mapクラスで管理します。
Map<String, String> params = new HashMap<String, String>();
params.put("format", FORMAT);
params.put("formatVersion", FORMAT_VERSION);
params.put("hits", HITS);
params.put("applicationId", applicationId);
if (!affiliateId.isEmpty())
params.put("affiliateId", affiliateId);
params.put("keyword", keyword);
params.put("genreId", genreId);
params.put("page", page.toString());
params.put("sort", sort);
「applicationId」は先述の「Application ID」で、必須パラメーターです。 「affiliateId」は先述の「Affiliate ID」で、必須パラメーターではありません。 「keyword」は検索キーワードで、必須パラメーターです。例えば「ダイニングテーブル」と指定します。 「genreId」はジャンルで、必須パラメーターです。例えば、楽天全体を検索する場合は「0」を指定します。指定できるパラメータはこちらで調べられます。 「format」はAPIレスポンスのタイプで、jsonやxmlが指定できます。私はjsonを指定しました。 「formatVersion」はjsonのときに指定できます。1がデフォルトですが、2を設定すると多少スマートなjsonが返ってきます。私は2を指定しました。 「hits」は検索結果の件数です。デフォルトは30です。1~30までを指定できます。 「page」は検索ページ番号です。デフォルトは1です。1~100までを指定できます。 「sort」はソート方法です。デフォルトは「standard」が指定されています。 他にも色々と指定できますが、基本的な動作は上記で十分です。 さて、これらをRestTemplateで指摘できるURLに変換します。「endpoint」は楽天商品検索APIのエンドポイントである「https://app.rakuten.co.jp/services/api/IchibaItem/Search/20140222」を入力します。
StringBuffer buffer = new StringBuffer();
for (Iterator<Entry<String,String>> it = params.entrySet().iterator(); it.hasNext();) {
Map.Entry<String,String> entry = it.next();
String key = entry.getKey();
buffer.append(String.format("%s={%s}", key,key));
if (it.hasNext()) {
buffer.append("&");
}
}
String url = String.format("%s?%s", endpoint, buffer.toString());
楽天のAPIはxsdファイルが古いバージョンのものしか公開されていなかったので、APIのレスポンスはMapクラスで受けます。ここが多少使いづらいところですが、問題なく使えます。楽天のAPIは1秒に1回までのrate limitがあるので、下記のようにしてリクエストに失敗した時のフェイルセーフをしておきます。
Map<String,Object> response = null;
int i=0;
while (i<5) {
try {
response = restTemplate.getForObject(url, Map.class, params);
break;
} catch (RestClientException e) {
LOG.error("RestClientException",e);
response = new HashMap<String,Object>();
i++;
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
LOG.error("InterruptedException",e);
}
}
商品名と価格を取るには、下記のようにします。注意事項ですが、下記サンプルコードは「formatVersion=2」のときのレスポンスをパースしたものなので、それぞれに合わせて読み替えてください。
List<Map> items = (List<Map>) response.get("Items");
for (Map item: items) {
String title = (String) item.get("itemName");
String price = String.format("¥ %,3d", (Integer) item.get("itemPrice"));
}
おわりに
楽天のAPIレスポンスはMapクラスで受けるのでAPIのレスポンスを把握しておく必要があり、多少使いづらいところがあります。それを差し置いてもJavaからAPIをこのような形で呼び出せるというのは非常に使いやすいと思います。