覚えたら書く

IT関係のデベロッパとして日々覚えたことを書き残したいです。twitter: @yyoshikaw

Kotlin - トリプルクォート文字列

現在のJavaにはなくてKotlinにはあるものの一つに トリプルクォート文字列(triple-quoted string) があります。

固定文字列は、"(ダブルクォート)で囲って記述しますが、
この際に、その文字列内に ダブルクォート を入れたり 改行を入れたりしようとすると 必ずエスケープが必要になってきます。

例えば以下のようなクラスを定義したとして

public class Person {
    private final long id;
    private final String name;
    private final int age;

    public Person(long id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

以下のJSON文字列から上記クラスのオブジェクトへと変換するものとします

{
    "id" : 10001,
    "name" : "KotorinTaro",
    "age" : 25
}

JSON文字列からこのオブジェクトに変換する処理をJavaで書こうとすると以下のようになります。
(今回の例では、変換に Gsonライブラリを使用しています)


JSON文字列からオブジェクトへの変換のコード(一部抜粋)

import com.google.gson.Gson;

// JSON文字列の定義
String json = "{ \"id\": 10001, \"name\": \"KotorinTaro\", \"age\": 25 }";

Gson gson = new Gson();
Person person = gson.fromJson(json, Person.class);

System.out.println(json + "\n -> " + person);

実行結果は以下の通りです

{ "id": 10001, "name": "KotorinTaro", "age": 25 }
 -> Person{id=10001, name='KotorinTaro', age=25}


一応、問題なく変換できているようですが、
そもそも元のJSON文字列の定義がエスケープだらけでJSON文字列として正しいのかよく分かりません。

String json = "{ \"id\": 10001, \"name\": \"KotorinTaro\", \"age\": 25 }";

同じ階層に3項目しかないJSONなので、まだマシと言えばマシですがかなり分かりにくいです。


普通のアプリで、わざわざJSONを文字列リテラルで記述することなんか無いでしょう・・・と思いたくなりますが、
たとえばユニットテストのインプットとしてJSON文字列などを使いたい(外部からJSONの電文が渡された想定の)場合などに、
JSON文字列を直接記述したくなります。

が、JSONを素直に記述することもできないので、JSONファイルを用意してその中にJSONを書いて、
ユニットテスト時に一旦そのファイルから読み取った文字列をテストケースに渡す。
といったことになりがちです。


トリプルクォート文字列

Kotlinのトリプルクォート文字列は以下のような記述をします

val str = """なんかの文字列"""


たとえば改行やダブルクォート等を含んだ文字列でもエスケープが必要ありません

◾️サンプルコード1

val str = """|"My Name is Kotorin Taro."|"""

println(str)

◾️実行結果

|"My Name is Kotorin Taro."|


◾️サンプルコード2

val str = """
     for (ch in "something") {
        println(ch)
    }
    """

    println(str)

◾️実行結果

    for (ch in "something") {
        println(ch)
    }


文字列の先行する空白行(左のマージン)を取り除いた状態にしたい場合は、マージンの終わりをマークするマージンプレフィックス(規定のマージンプレフィックスは | (パイプ))と trimMargin関数を使用します。

◾️サンプルコード3

val str = """
    |for (ch in "something") {
    |    println(ch)
    |}
    """.trimMargin()

println(str)

◾️実行結果

for (ch in "something") {
    println(ch)
}


当初のJSON文字列をオブジェクト化するサンプルをKotlinで以下のように書く事ができます

import com.google.gson.Gson

val json = """
    |{
    |    "id" : 10001,
    |    "name" : "KotlinTaro",
    |    "age" : 25
    |}
    """.trimMargin()

val person = Gson().fromJson(json, Person::class.java)

println("$json \n-> $person")

実行結果は以下の通りです

{
    "id" : 10001,
    "name" : "KotlinTaro",
    "age" : 25
} 
-> Person{id=10001, name='KotlinTaro', age=25}


まとめ

Kotlin の トリプルクォート文字列 を利用する事で、通常であればエスケープを必要とするような文字列も素直に記述できる事が分かりました。
ここには書きませんでしたが、正規表現の記述の場合にも トリプルクォート文字列 が有効に利用できます。