LoginSignup
45
36

More than 5 years have passed since last update.

Swift4のJSONDecorderは、Date等のパース方法をカスタマイズできるみたい

Posted at

とりあえずサンプルコード

import Foundation

struct S1: Codable {
    let dateFromTimeInterval: Date
}

struct S2: Codable {
    let dateFromISO8601: Date
}

struct S3: Codable {
    let dateFromCustomFormat: Date
}

let data = """
{
    "dateFromTimeInterval": 540000000,
    "dateFromISO8601": "2017-01-01T12:34:56Z",
    "dateFromCustomFormat": "2034ねん03がつ04にち05じ06ふん07びょう",
}
""".data(using: .utf8)!

do {
    do {
        let decoder = JSONDecoder()
        let t = try decoder.decode(S1.self, from: data)
        print(t)
    }
    do {
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .iso8601
        let t = try decoder.decode(S2.self, from: data)
        print(t)
    }
    do {
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .formatted({
            let f = DateFormatter()
            f.calendar = Calendar(identifier: .gregorian)
            f.locale = .current
            f.dateFormat = "yyyyねんMMがつddにちHHじmmふんssびょう"
            return f
        }())

        let t = try decoder.decode(S3.self, from: data)
        print(t)
    }
    do {
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .custom {
            let container = try $0.singleValueContainer()
            let str = try container.decode(String.self)
            let f = DateFormatter()
            f.calendar = Calendar(identifier: .gregorian)
            f.locale = .current
            f.dateFormat = "yyyyねんMMがつddにちHHじmmふんssびょう"
            return f.date(from: str)!
        }
        let t = try decoder.decode(S3.self, from: data)
        print(t)
    }
} catch {
    print(error)
}

/* 結果
S1(dateFromTimeInterval: 2018-02-11 00:00:00 +0000)
S2(dateFromISO8601: 2017-01-01 12:34:56 +0000)
S3(dateFromCustomFormat: 2034-03-04 13:06:07 +0000)
S3(dateFromCustomFormat: 2034-03-04 13:06:07 +0000)
*/

Date以外も、Strategyとして設定できるものはいくつかあるみたい

    /// The strategy to use for decoding `Date` values.
    public enum DateDecodingStrategy {

        /// Defer to `Date` for decoding. This is the default strategy.
        case deferredToDate

        /// Decode the `Date` as a UNIX timestamp from a JSON number.
        case secondsSince1970

        /// Decode the `Date` as UNIX millisecond timestamp from a JSON number.
        case millisecondsSince1970

        /// Decode the `Date` as an ISO-8601-formatted string (in RFC 3339 format).
        case iso8601

        /// Decode the `Date` as a string parsed by the given formatter.
        case formatted(DateFormatter)

        /// Decode the `Date` as a custom value decoded by the given closure.
        case custom((Decoder) throws -> Date)
    }

    /// The strategy to use for decoding `Data` values.
    public enum DataDecodingStrategy {

        /// Decode the `Data` from a Base64-encoded string. This is the default strategy.
        case base64Decode

        /// Decode the `Data` as a custom value decoded by the given closure.
        case custom((Decoder) throws -> Data)
    }

    /// The strategy to use for non-JSON-conforming floating-point values (IEEE 754 infinity and NaN).
    public enum NonConformingFloatDecodingStrategy {

        /// Throw upon encountering non-conforming values. This is the default strategy.
        case `throw`

        /// Decode the values from the given representation strings.
        case convertFromString(positiveInfinity: String, negativeInfinity: String, nan: String)
    }

    /// The strategy to use in decoding dates. Defaults to `.deferredToDate`.
    open var dateDecodingStrategy: JSONDecoder.DateDecodingStrategy

    /// The strategy to use in decoding binary data. Defaults to `.base64Decode`.
    open var dataDecodingStrategy: JSONDecoder.DataDecodingStrategy

    /// The strategy to use in decoding non-conforming numbers. Defaults to `.throw`.
    open var nonConformingFloatDecodingStrategy: JSONDecoder.NonConformingFloatDecodingStrategy

ちなみに、JSONDecoder だけでなく JSONEncoder 側にもカスタマイズ可能なプロパティがいくつかあるので覚えておくとよさそう

参考リンク

JSONDecoder - Foundation | Apple Developer Documentation
JSONEncoder - Foundation | Apple Developer Documentation

45
36
1

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
45
36