Swift's JSONDecoder
offers a dateDecodingStrategy
property, which allows us to define how to interpret incoming date strings in accordance with a DateFormatter
object.
However, I am currently working with an API that returns both date strings (yyyy-MM-dd
) and datetime strings (yyyy-MM-dd HH:mm:ss
), depending on the property. Is there a way to have the JSONDecoder
handle this, since the provided DateFormatter
object can only deal with a single dateFormat
at a time?
One ham-handed solution is to rewrite the accompanying Decodable
models to just accept strings as their properties and to provide public Date
getter/setter variables, but that seems like a poor solution to me. Any thoughts?
Please try decoder configurated similarly to this:
lazy var decoder: JSONDecoder = {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in
let container = try decoder.singleValueContainer()
let dateStr = try container.decode(String.self)
// possible date strings: "2016-05-01", "2016-07-04T17:37:21.119229Z", "2018-05-20T15:00:00Z"
let len = dateStr.count
var date: Date? = nil
if len == 10 {
date = dateNoTimeFormatter.date(from: dateStr)
} else if len == 20 {
date = isoDateFormatter.date(from: dateStr)
} else {
date = self.serverFullDateFormatter.date(from: dateStr)
}
guard let date_ = date else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Cannot decode date string \(dateStr)")
}
print("DATE DECODER \(dateStr) to \(date_)")
return date_
})
return decoder
}()