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にあります。

github.com

soushin.sandbox.kt.jackson を参照してください。