【Swift】Date型をJSON化する際に注意するべきこと!エポック秒で情報の欠落

【Swift】Date型をJSON化する際に注意するべきこと!エポック秒で情報の欠落

この記事からわかること

  • SwiftDate(日付)型をJSON変換するには?
  • エンコードする際の注意
  • エポック秒とは?
  • DateEncodingStrategyで指定できる値

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

Date型をJSONに変換する際の注意点

SwiftでDate型をプロパティに持つ構造体などをJSONに変換したい場合JSONEncoder/JSONDecoderを使用することで特に意識せずに相互に変換が可能になります。

struct AppNotify: Identifiable, Codable {
    public var id: UUID = UUID()
    public var title: String
    public var msg: String
    public var time: Date = Date()
}
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrintedguard 
let jsonData = try? encoder.encode(notification) else { return }
guard let json = String(data: jsonData, encoding: .utf8) else { return }
print(json)

例えば上記の構造体をそのまま変換すると以下のように741670569.590185という形式でJSON化されます。

{
    "time": 741670569.590185,
    "msg": "通知メッセージ",
    "title": "通知タイトル",
    "id": "7964108A-4F26-4DD1-B421-1607AA1EA3E6"
}

エポック秒形式(UNIX時間)

741670569.590185エポック秒またはUNIX時間と呼ばれ1970年1月1日00:00:00 UTC(協定世界時)からの経過時間を秒単位で表したものになります。

SwiftではDate型のtimeIntervalSince1970プロパティからその日付のエポック秒を取得することが可能です。しかしJSONで変換した際のエポック秒とtimeIntervalSince1970プロパティで取得したエポック秒が異なりました

Date().timeIntervalSince1970 // 1719977769.5901852

JSON変換したエポック秒は情報が抜け落ちている

以下のエポック秒は2024年7月3日 3:36:09Date型をそれぞれエポック秒に変換したものです。値が異なっているのが確認できます。

JSONデコード:741670569.590185
timeIntervalSince1970プロパティ:1719977769.5901852

741670569.590185の値をJSONをエンコードすると正常に2024-07-03T03:36:09Zの日付になるのですが、日付に直そうとすると1993-07-03T03:36:09Zになってしまいました。

JSONでそのままDate型を変換するとJSONのエンコードでしか正しい日付に戻せないエポック秒になってしまうので注意が必要です。Androidなどで同じデータを扱う際には正しく変換できなくなってしまうので別の形式に変換する必要があります。

ISO8601形式でJSON化する

エポック秒だと情報が抜け落ちてしまうためISO8601形式でJSON化させることができます。JSONEncoderdateEncodingStrategyプロパティにiso8601を指定することで2024-07-03T03:36:09Zという形式の文字列にすることが可能です。

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
encoder.dateEncodingStrategy = .iso8601
guard let jsonData = try? encoder.encode(notifications) else { return }
guard let json = String(data: jsonData, encoding: .utf8) else { return }
print(json)

これなら別の環境でも日付に変換できるようになると思います。しかしこの場合は最小単位が秒数になり、先ほどのエポック秒で取得できていたミリ秒以下.5901852は欠落してしまうので注意してください。

{
    "time": "2024-07-03T03:36:09Z",
    "msg": "通知メッセージ",
    "title": "通知タイトル",
    "id": "7964108A-4F26-4DD1-B421-1607AA1EA3E6"
}

またデコードする際JSONDecoderdateEncodingStrategyiso8601を指定する必要があります。

decoder.dateEncodingStrategy = .iso8601

dateEncodingStrategyに設定できる値

dateEncodingStrategyに設定できる値DateEncodingStrategy型は他にも以下のように変換できました。こちらもデコードする際は変換したDateEncodingStrategyJSONDecoderdateEncodingStrategyに指定します。

millisecondsSince1970

encoder.dateEncodingStrategy = .millisecondsSince1970
"time" : 1719977769590.185

secondsSince1970

encoder.dateEncodingStrategy = .secondsSince1970
"time" :  1719977769.5901852

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index