KotlinでHTTP通信してJSONにする

2023/03/20 追記・編集

1年ほど前に書いたこちらの記事が想像以上に読まれているようでとても驚いています。 こちらで紹介していたコードはあまりKotlinらしい記法ではなかったため、情報の質として良くないと判断し コード部分の編集を行いました。

差分は以下リンクから参照することができます。

https://gist.github.com/rokuosan/3aa7fd1ff8c609361d72cc49d3a98f73/revisions

はじめに

Kotlinを使ってHTTPリクエストを送信し、レスポンスをJSONとして解析する方法を忘れないために書き残しておきます。

JSONの解析には外部ライブラリを用いますが、HTTP通信には標準ライブラリのみを使用します。

外部ライブラリなどを使用すれば、もっと簡潔に書けると思いますしそちらの方が機能面でも優れてるかと思います。 もしライブラリを使用する場合であれば、Fuelなどのライブラリを使用すれば良いでしょう。

ここに紹介するサンプルコードでは行数の少なさを優先したためnull安全が十分ではありません。 実際に利用する際はnullチェックなどを挟んでnull安全に利用してください。

HTTP通信を行う

KotlinでHTTP通信を行うにはHttpURLConnectionか、HttpsURLConnectionを使います。

今回では、HTTPを選択します。

KotlinでHttpURLConnectionを使って通信を行うには以下のように記述します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.net.HttpURLConnection
import java.net.URL

fun main(){
    // URL 設定
    val url = URL("接続するURL")
    val con = url.openConnection() as HttpURLConnection

    // 接続設定(ミリ秒で指定)
    con.connectTimeout = 20_000 // 20 秒
    con.readTimeout = 20_000    // 20 秒
    con.requestMethod = "GET"   // GETの場合は省略可能

    // 接続を確立
    con.connect()

    // レスポンスを取得
    val str = con.inputStream.bufferedReader(Charsets.UTF_8).use { br ->
            br.readLines().joinToString("")
    }

    // 表示
    println(str)
}

requestMethodに関してはデフォルトでGETなので変更する必要がない場合は記述する必要はありません。

文字列結合についてはjoinToString()で行っています。この関数は引数に指定された文字列を利用してリストにある文字列をすべて結合してくれます。 デフォルトでは区切り文字としてカンマが渡されてしまうので、空の文字列を指定しておきます。

Kotlinの標準ライブラリにあるbuildStringを利用して文字列を結合しても問題ありません。

buildStringを利用した場合は以下のように書き換えることができます。

1
2
3
4
5
6
// レスポンスを取得
val str = buildString {
        con.inputStream.bufferedReader(Charsets.UTF_8).use { br ->
            br.readLines().forEach(this::append)
        }
    }

また、use{ /* 処理 */ }と記述すると、Javaではcloseしていたものを自動でcloseしてくれます。非常に便利です。

JSONにする

JSONに変換するにあたって、JSON in Java1 というライブラリを用います。

KotlinにはKotlin Serializationと呼ばれる公式シリアライザが用意されていますが、準備の少なさからこちらを今回は利用します。

このライブラリを使用するためにはGradleを使用している場合であれば、以下のものを追記してください。

1
2
3
4
5
6
7
8
repositories {
    mavenCentral()
}

dependencies {
    // https://mvnrepository.com/artifact/org.json/json
    implementation("org.json:json:20230227")
}

ライブラリを使用できるようになったところで、先ほどのプログラムに変更を加えます。

 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
import org.json.JSONArray
import java.net.HttpURLConnection
import java.net.URL

fun main() {
    // URL 設定
    val url = URL("接続するURL")
    val con = url.openConnection() as HttpURLConnection

    // 接続設定
    con.connectTimeout = 20_000 // 20 sec
    con.readTimeout = 20_000    // 20 sec
    con.requestMethod = "GET"   // GET Method

    // 接続を確立
    con.connect()

    // レスポンスを取得
    val str = con.inputStream.bufferedReader(Charsets.UTF_8).use { br ->
        br.readLines().joinToString("")
    }

    // JSON変換
    // {} の場合はJSONObject,
    // [] の場合はJSONArrayを利用してください.
    val json = JSONObject(str)

    // 表示
    println(json.toString())

}

レスポンスのデータが{で始まっている場合は、JSONObjectクラスを利用してください。 もし[から始まっている場合はJSONArrayクラスを利用してください。

どちらにおいてもコンストラクタに変換したい文字列を渡せばあとはJSONデータとして扱うことができます。

あとは、自由にデータを取得したりすれば終わりです。

さいごに

KotlinでHTTP通信してレスポンスをJSONに変換するプログラムを作りました。

たまにHTTP通信の方法を忘れてしまうので、今度こそ忘れないようにしたいです。