在Swift中使用不同的JSON格式解码日期值?

时间:2019-09-05 22:29:30

标签: json swift codable

假设我们具有以下结构:

struct TestCod: Codable {
    var txt = ""
    var date = Date()
}

如果我们期望JSON具有两种相似的格式,那么如何处理解码?

JSON A:

{
"txt":"stack",
"date":589331953.61679399
}

JSON B:

{
"txt":"overflow",
"date":"2019-09-05"
}

1 个答案:

答案 0 :(得分:2)

如我已经在评论中提到的可能重复的帖子中所示,您需要创建一个自定义日期解码策略:

首先创建用于解析日期字符串的日期格式化程序(请注意,这假定您的日期是本地时间,如果您需要UTC时间或服务器时间,则需要相应地设置格式化程序时区属性):

extension Formatter {
    static let yyyyMMdd: DateFormatter = {
        let formatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter
    }()
}

然后创建自定义解码策略,以尝试您可能需要的所有可能的日期解码策略:

extension JSONDecoder.DateDecodingStrategy {
    static let deferredORyyyyMMdd  = custom {
        let container = try $0.singleValueContainer()
        do {
            return try Date(timeIntervalSinceReferenceDate: container.decode(Double.self))
        } catch {
            let string = try container.decode(String.self)
            if let date = Formatter.yyyyMMdd.date(from: string)  {
                return date
            }
            throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid date: \(string)")
        }
    }
}

游乐场测试:

struct TestCod: Codable {
    let txt: String
    let date: Date
}

let jsonA = """
{
"txt":"stack",
"date":589331953.61679399
}
"""
let jsonB = """
{
"txt":"overflow",
"date":"2019-09-05"
}
"""

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .deferredORyyyyMMdd
let decodedJSONA = try! decoder.decode(TestCod.self, from: Data(jsonA.utf8))
decodedJSONA.date  //  "Sep 4, 2019 at 8:19 PM"
let decodedJSONB = try! decoder.decode(TestCod.self, from: Data(jsonB.utf8))
decodedJSONB.date  //  "Sep 5, 2019 at 12:00 AM"