jackson.datatypeをつかってiOSのレシートの日付文字列をデシアライズする
iOSアプリで購入したアイテムのレシート検証を実装する過程でレシートに含まれる日付文字列をdata classにデシアライズしてみた。
レシートに含まれる日付は次のような形となっている。
"expires_date": "2016-06-17 01:32:28 Etc/GMT"
見慣れないタイムゾーンを表すEtc/GMT
の文字列があった。
DateTimeFormatter (Java Platform SE 8 )
上記を参照すると次のように定義されている。
V time-zone ID zone-id America/Los_Angeles; Z; -08:30
この定義からDateTimeFormatter は次のように定義する必要がある。※ Vは2つVV
。
"yyyy-MM-dd HH:mm:ss VV"
このフォーマットをもとにJson文字列から定義したdata classへデシアライズしてみよう。
デシアライズするdata classを定義する
デシアライズするdata classは次のようなに定義した。
data class MyState( @JsonProperty("expiration_date") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss VV") val expirationDate: ZonedDateTime )
JSONにあるexpiration_date
はdata classでは文字列ではなく日付系の型に変換したい。
ここで重要な点がある。
日付文字列にはEtc/GMT
のタイムゾーンが含まれるためLocalDateTimeには変換できない。LocalDateTimeはタイムゾーンを持たないからである。
そのためZonedDateTime
に変換し expirationDate.toLocalDateTime()
とすることでLocalDateTimeが取得することができる。
data classの準備はこれで整った。
jackson.datatypeをつかう
ここでエントリのタイトルにもあるjackson.datatype
が登場する。
Json <-> DataClassのシリアライズ/デシアライズにはkotlinモジュールも整っているのでjackson
を採用したい。
日付型に変換が必要であればjackson.datatype
が必要である。gradleに依存を追加する。
compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.1'
そしてObjectMapperの初期化にJavaTimeModule
を追加する。
val objectMapper = ObjectMapper() .registerModule(KotlinModule()) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .registerModule(JavaTimeModule())
これでiOSのレシートでつかわれる日付文字列を日付型に定義したdata classにデシアライズできる。
class SandboxTest { @Test fun deserialize() { Sandbox.deserialize<MyState>(json).let { format(formatter)(it.expirationDate.toLocalDateTime()) shouldBe "2016-06-17 01:27:28" } } private fun format(f: DateTimeFormatter): (LocalDateTime) -> String { return { date -> f.format(date) } } private val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") private val json = """ { "expiration_date": "2016-06-17 01:27:28 Etc/GMT" } """ }
まとめ
2016-06-17 01:32:28 Etc/GMT
のようなフォーマットをjacksonでデシアライズする方法をまとめた。- タイトルのナレッジの日本語エントリが少なかったのとレシート検証している人も多いだろうし備忘録として溜めておく。
コード
コードはgithubにあります。
soushin.sandbox.kt.jackson
を参照してください。