jackson.datatypeをつかってiOSのレシートの日付文字列をデシアライズする


iOSアプリで購入したアイテムのレシート検証を実装する過程でレシートに含まれる日付文字列をdata classにデシアライズしてみた。

レシートに含まれる日付は次のような形となっている。

1
"expires_date": "2016-06-17 01:32:28 Etc/GMT"

見慣れないタイムゾーンを表すEtc/GMTの文字列があった。

DateTimeFormatter (Java Platform SE 8 )

上記を参照すると次のように定義されている。

1
V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30

この定義からDateTimeFormatter は次のように定義する必要がある。※ Vは2つVV

1
"yyyy-MM-dd HH:mm:ss VV"

このフォーマットをもとにJson文字列から定義したdata classへデシアライズしてみよう。

デシアライズするdata classを定義する

デシアライズするdata classは次のようなに定義した。

1
2
3
4
5
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に依存を追加する。

1
compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.1'

そしてObjectMapperの初期化にJavaTimeModuleを追加する。

1
2
3
4
val objectMapper = ObjectMapper()
        .registerModule(KotlinModule())
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        .registerModule(JavaTimeModule())

これでiOSのレシートでつかわれる日付文字列を日付型に定義したdata classにデシアライズできる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class SandboxTest {

    @Test
    fun deserialize() {
        Sandbox.deserialize&lt;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"
}
"""
}

まとめ

コード

コードはgithubにあります。

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