I am using Swift 4 to decode some JSON from Twitter:
struct Tweet: Codable {
let id: String
let createdAt: Date
let text: String
enum CodingKeys: String, CodingKey {
case id = "id_str"
case createdAt = "created_at"
case text
}
}
let decoder = JSONDecoder()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "eee MMM dd HH:mm:ss ZZZZ yyyy"
decoder.dateDecodingStrategy = .formatted(dateFormatter)
let tweets = try decoder.decode([Tweet].self, from: data!)
How can I make it so my code doesn't have to keep remembering to set decoder.dateDecodingStrategy
. Ideally the Tweet
struct would be aware of its date format with a dateFormatter
constant static member variable initialised to the correct format.
I imagine I need to use init(decoder: Decoder)
somehow on Tweet
but I am not sure how.
You can extend Formatter and create a custom static DateFormatter.
extension Formatter {
static let custom: DateFormatter = {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "eee MMM dd HH:mm:ss ZZZZ yyyy"
return formatter
}()
}
And if you would like to make Tweet parse your date string you can provide your own custom decoder initializer as follow:
extension Tweet {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(String.self, forKey: .id)
text = try container.decode(String.self, forKey: .text)
createdAt = try Formatter.custom.date(from: container.decode(String.self, forKey: .createdAt))!
}
}
This assumes that your date string it is properly formatted, if your date string is not guarantee to be properly formatter you can make your Date property optional and remove the force unwrap from the date(from: String) method.