LoginSignup
10
9

More than 5 years have passed since last update.

KotlinでGsonでパースした時の挙動の調査

Posted at

Kotlin書いてて、基本的にはvalで宣言してかつ書けるのであればnon-nullな形で書いていくのが良い書き方だなぁと考えている。

data classでGsonを使ってパースした時に、non-nullな形で書きたい。
しかし、Jsonはnullとか、そもそもキーが欠落していたりとか、Kotlinのnon-nullでは表せない状態を取る事が出来る。
そうなった時に一体どのような挙動するのか、どのように書くとそのような挙動を吸収できるのか?疑問に思ったので試してみた。

例えば、以下のような感じで書いた時にGsonでパースした結果がどうなるかについて調べた。

NonNullで定義しているケース

data class UserNonNull(
        val id: Int,
        val name: String,
        @SerializedName("has_family")
        val hasFamily: Boolean
)

Nullableで定義しているケース

data class UserNullable(
        val id: Int?,
        val name: String?,
        @SerializedName("has_family")
        val hasFamily: Boolean?
)

パースするJsonは正常系、すべてnullが入った場合、そもそもキーがない場合の3パターン。
合計6パターンでどうなるか調べた。

検証したテストケースはこの辺にアップしているのでご覧ください。
https://github.com/mapyo/GsonKotlinSample/blob/master/app/src/test/java/com/mapyo/gsonkotlinsample/GsonSampleUnitTest.kt

結果

調べてる途中にそりゃそうだわー。と思ってきたので詳細は↑に書いてたテストケースのURLを御覧ください。
KotlinのByteCodeを表示してJavaにデコンパイルするとよくわかる。

val id: Int
↓
int id;
val id: Int?
↓
Integer id;

という具合のjavaコードが生成されるからだ。Gsonでパースした結果は、Javaのそれと同じ。
intだとjsonがnullでも0になるし、Integerだとjsonがnullだとnullになる。

Stringの場合は違う。

val name: String
↓
@NotNull
String name;
val name: String?
↓
@Nullable
String name;

NotNullがついているとはいえ、jsonがnullの場合やキーがない場合は容赦なくnullになる。なので、val name: Stringで宣言してても、nullが入ってきて、それを使おうとするとぬるぽになる。

余談だが、AndroidのNullじゃないアノテーションは@NonNullで表されてるけど、
KotlinをJavaに変換した時は、@NotNullという名前がつけられてるんだなぁ。

僕の意見

Gsonでパースするときは、生成されるJavaコードを意識しつつ、
Jsonでnullが入ってくるのかどうか。キーが必ずあるのかどうか。
を意識して、NonNullにするか、Nullableにするか選択しましょう。

val name: Stringとしていても、Jsonの内容によってはNullが返ってくるので注意。
これは、別のクラスや配列などをパースするようにしていても同じ事だと思う。
未検証だけど、生成されるJavaのコードの事を考えるとそうなるはず。

この辺をある程度わかった上でコードを書いてると厚みが出るかなぁと思った。そんな今日この頃。

10
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9