引き続きShangriLaを例にしていますが、今度はGroovyでGETリクエストの実行と返却されたJSON文字列を処理してみました。
おや、Gradleサイトの様子が・・・!
README書くためにGradleのサイトに行ったところ、サイトがリニューアルしていました。
どうもgradle.comというコミュニティサイトっぽいものを作るから先行登録してね、 みたいなことを通知したいためのようです。 今のところサイトには簡単なGradleの使い方が載ってるぐらいで、 ほとんど情報はなく、このサイトがどうなっていくのかは不明です。
自分としては、ただGradleのインストール手順までの遷移がわかり辛くなったな、と感じただけでした。
なので、インストール手順が書いてあるページを以下にリンクしておきます。
HTTPBuilderでのGET方法
GroovyでHTTP通信をするのであれば、HTTPBuilderを使うのが良いと思います。
HttpBuilderの設定
build.gradleのdependenciesにhttp-builderを追加すると、対象のGradleプロジェクトから利用可能になります。
- build.gradle
repositories { mavenCentral() } dependencies { compile ('org.codehaus.groovy:groovy-all:2.4.5') {transitive = false} compile 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.1' }
以前はbuild.gradleのrepositoriesに、HTTPBuilderが置いてあるMavenリポジトリのパスを2つ追記し、 以下のようにする必要がありましたが、現在はこの指定は不要になっているようです。
- 昔の書き方
repositories { mavenCentral() maven { // for HTTP Builder url "http://repository.codehaus.org" url "http://snapshots.repository.codehaus.org" } }
GETリクエストの送信方法
HTTPBuilderクラスのgetメソッドを呼ぶ方法と、requestメソッドで実行する方法があります。
記載の通りに実行すればGETリクエストを送信できますが、せっかくなので色々試してみました。
requestメソッドの利用方法
公式の記述のように、HTTPBuilderクラスの引数を指定せずに、requestメソッドの第1引数にホスト名を渡す方法でもできますが、省略して以下のように書くこともできます。
def http = new HTTPBuilder("http://api.moemoe.tokyo") def resJsonText = http.request(GET, TEXT) { uri.path = '/anime/v1/master/cours' headers.Accept = 'application/json' response.success = { resp, json -> assert resp.status == 200 def jsonString = json.text println("GET /anime/v1/master/cours json response: $jsonString") jsonString } response.'404' = { resp -> println "Access denied" } response.failure = { resp -> println "Unexpected failure: ${resp.statusLine}" } }
ヘッダー情報も付ける必要がなければ付けなくても動作します。もちろん付けたければ公式のように色々付けれます。
ちなみにresponse.'404'
とresponse.failure
のときのresJsonTextの戻り値はnull
になります。何も返してないですからね。
はまりポイント
HTTPBuilderのパラメータや、requestメソッドの第1引数にホスト名以降を書くと、404になります。
また、uriの指定で先頭に/
がないとエラーになります。
getメソッドの利用方法
これは公式にある通りに書けば大丈夫なので、上記のサンプルを書き直すと以下のような感じになります。
def http = new HTTPBuilder("http://api.moemoe.tokyo") def resJsonText = http.get( path : '/anime/v1/master/cours', contentType : TEXT) { resp, json -> if (resp.status < 400) { def jsonString = json.text println("GET /anime/v1/master/cours json response: $jsonString") jsonString } else if (resp.status == 404) { println "Access denied" } else { println "Unexpected failure: ${resp.statusLine}" } }
結果を受け取ることだけを考えると記述量が減って簡単ですが、リクエストの成功と失敗の判断を自前でやることになるので、状況によって使い分けるべきですね。
switchで書いた方が綺麗かも。
GroovyでJSONを扱う
次に返却値のJSONを処理するために、groovy.jsonのJsonSlurperクラスを使います。
Scalaを書いた後だったからなのか、これ、すごく便利に感じました。Groovyの最強感がすごい。
JSON文字列をGroovyで扱えるJSONオブジェクトに変換する
JsonSlurperを使ってJSONオブジェクトを作るのはとても簡単です。
JsonSlurper#parseTextメソッドにJSON文字列を渡すだけで完了します。
def jsonSlurper = new JsonSlurper() def resJsonObj = jsonSlurper.parseText('{"3":{"id":3,"year":2014,"cours":3}}')
こうして作成したJSONオブジェクトは、JSONデータをMapで表現するため、直感的に扱うことができます。
Mapなので、キーを得たい場合はresJsonObj.key
、値を得たい場合はresJsonObj.value
で取得できますし、
キーを指定して値を得たい場合はassert resJsonObj.value.year == 2014
のように、
キーの要素で指定するだけです。ポイントはvalue値がダブルクォート無しの数値であれば、ちゃんと数値型で取り出せるというところでしょうか。なので文字列比較にしていると失敗します。
今回のサンプルコード
今回の解説で利用したサンプルコードのベースとなるGroovyプロジェクトは、以下になります。こっちではもうちょっと色々やっているので、ぜひこちらもご覧ください。
正月早々
帰省中にプログラミングしようと思っていたのですが、このサンプルを書いたところで風邪でダウンしてしまいました。 今年は家に引きこもるのもほどほどにして、少し体力をつけて病気に負けないようにしたいです。
そして、久しぶりにGroovyでコード書きましたが、びっくりするぐらいに書きやすかったです、Groovy。
前回、ScalaでJSON操作するのに四苦八苦したことを考えると、JsonSlurperの直感性は感動的でした。
なかなかプロダクトで使うのは難しい言語ですが、個人的にはこれからも使っていくので、都度トピックを紹介させて頂こうと思っています。
もし興味を持っていただけたのであれば、試しに今まで書いたJavaのコードをGroovyに変換してみてください。そうすると魅力に気付きやすいかと思います。
そして慣れてきたら、是非Spockを使ってGroovyでテストコードを書きましょう!