Swift 5
实际上,基于@BrownsooHan版本使用了JSONDecoder
扩展。
JSONDecoder+dateDecodingStrategyFormatters.swift
extension JSONDecoder {
var dateDecodingStrategyFormatters: [DateFormatter]? {
@available(*, unavailable, message: "This variable is meant to be set only")
get { return nil }
set {
guard let formatters = newValue else { return }
self.dateDecodingStrategy = .custom { decoder in
let container = try decoder.singleValueContainer()
let dateString = try container.decode(String.self)
for formatter in formatters {
if let date = formatter.date(from: dateString) {
return date
}
}
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Cannot decode date string \(dateString)")
}
}
}
}
这是一种有点hacky的方式,可以添加一个只能设置的变量,但您可以通过 func setDateDecodingStrategyFormatters(_ formatters: [DateFormatter]? )
轻松地转换 var dateDecodingStrategyFormatters
。
用法
假设您已经在代码中定义了几个DateFormatter
,如下所示:
extension DateFormatter {
static let standardT: DateFormatter = {
var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
return dateFormatter
}()
static let standard: DateFormatter = {
var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return dateFormatter
}()
static let yearMonthDay: DateFormatter = {
var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
return dateFormatter
}()
}
现在你可以通过设置 dateDecodingStrategyFormatters
直接将它们分配给解码器:
struct Dates: Codable {
var date1: Date
var date2: Date
var date3: Date
}
let jsonData = """
{
"date1": "2019-05-30 15:18:00",
"date2": "2019-05-30T05:18:00",
"date3": "2019-04-17"
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
decoder.dateDecodingStrategyFormatters = [ DateFormatter.standardT,
DateFormatter.standard,
DateFormatter.yearMonthDay ]
do {
let dates = try decoder.decode(Dates.self, from: jsonData)
print(dates)
} catch let err as DecodingError {
print(err.localizedDescription)
}
注释
我知道将 dateDecodingStrategyFormatters
设置为 var
有些hacky,我不建议这样做,你应该定义一个函数来代替。然而,这是个人喜好而已。