The issue there is in your JSONDecoder dateDecodingStrategy. The default strategy is called deferredToDate
which means it is expecting the timeIntervalSinceReferenceDate
. What you need is a custom dateFormat to parse your ISO8601 date format. Check this How to convert a date string with optional fractional seconds using Codable in Swift?.
Just create a custom DateFormatter iso8601 with and without fractional seconds:
extension Formatter {
static let iso8601withFractionalSeconds: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
return formatter
}()
static let iso8601: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
return formatter
}()
}
And a custom dateDecodingStrategy:
extension JSONDecoder.DateDecodingStrategy {
static let customISO8601 = custom {
let container = try $0.singleValueContainer()
let string = try container.decode(String.self)
if let date = Formatter.iso8601withFractionalSeconds.date(from: string) ?? Formatter.iso8601.date(from: string) {
return date
}
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid date: \(string)")
}
}
Now you can set your JSONDecoder dateDecodingStrategy properly:
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .customISO8601
And use that decoder to parse your JSON string. Note that if you use try? you are discarding the error which you should use to debug your issue:
return try decoder.decode([User].self, from: json)
} catch {
print(error)
}