我正在使用Swift 4解码来自Twitter的一些JSON:
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!)
如何制作,以便我的代码不必记住设置decoder.dateDecodingStrategy
。理想情况下,Tweet
结构将知道其日期格式,并将dateFormatter
常量静态成员变量初始化为正确的格式。
我想我需要在init(decoder: Decoder)
以某种方式使用Tweet
,但我不确定如何。
答案 0 :(得分:1)
正如@Larme在评论中所建议的那样,您可以继承JSONDecoder
并覆盖其init
方法,您可以将dateDecodingStrategy
设置为Twitter的日期格式。您还应该确保正确设置locale
的{{1}},否则它无法正确解码日/月名称。我认为这些都是英文版,因此我建议您使用DateFormatter
Locale
作为硬编码日期格式。
en_US_POSIX
然后,您只需在解码响应时初始化class JSONTweetDecoder: JSONDecoder {
private static let dateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "eee MMM dd HH:mm:ss ZZZZ yyyy"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
return dateFormatter
}()
override init() {
super.init()
self.dateDecodingStrategy = .formatted(JSONTweetDecoder.dateFormatter)
}
}
而不是JSONTweetDecoder
。
JSONDecoder
答案 1 :(得分:0)
您可以扩展Formatter并创建自定义静态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
}()
}
如果您想让Tweet解析您的日期字符串,您可以提供自己的自定义解码器初始化程序,如下所示:
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))!
}
}
这假设您的日期字符串格式正确,如果您的日期字符串不能保证格式正确,您可以使Date属性可选,并从日期(from:String)方法中删除强制解包。