假设我需要将从Web服务收到的日期字符串转换为Date对象。
使用ObjectMapper,很简单:
class Example: Mappable {
var date: Date?
required init?(map: Map) { }
func mapping(map: Map) {
date <- (map["date_of_interest"], GenericTransform().dateTransform)
}
}
我只需要为日期实现一个转换器(在这种情况下为“ GenericTransform”),然后将其作为参数以及要解密的密钥名称传递即可。
现在,使用Codable:
class Example2: Codable {
var name: String
var age: Int
var date: Date?
enum CodingKeys: String, CodingKey {
case name, age
case date = "date_of_interest"
}
}
根据我的理解,要更改日期,我必须执行以下操作之一:
1)将dateDecodingStrategy传递给我不需要的JSONDecoder,因为我试图将那部分代码保留为通用函数。
或
2)在示例2内实现一个init(from decoder: Decoder)
,我也不希望这样做,因为我不得不编写样板代码来解码所有其他属性(否则将自动生成):
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
age = try container.decode(Int.self, forKey: .age)
let dateString = try container.decode(String.self, forKey: .date)
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
if let date = formatter.date(from: dateString) {
self.date = date
} else {
//throw error
}
}
我的问题是:有没有比上面的选项1和2更简单的方法? 也许以某种方式调整CodingKeys枚举?
编辑:
实际上,问题不仅在于日期。在我正在从事的这个项目中,使用ObjectMapper的TransformOf<ObjectType, JSONType>
完成了许多自定义转换。
例如,使用以下代码完成从Web服务接收到的十六进制代码到UIColor的颜色转换:
let colorTransform = TransformOf<UIColor, String>(fromJSON: { (value) -> UIColor? in
if let value = value {
return UIColor().hexStringToUIColor(hex: value)
}
return nil
}, toJSON: { _ in
return nil
})
我正尝试从项目中删除ObjectMapper,并使用Codable进行这些相同的转换,因此仅使用自定义的dateDecodingStrategy是不够的。
你们会怎么做?为每个必须解码的类实现自定义init(from decoder: Decoder)
,例如彩色十六进制代码?
答案 0 :(得分:1)
在您的情况下使用dateDecodingStrategy
(因为您仅引用单个日期格式)非常简单……
let decoder = JSONDecoder()
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
decoder.dateDecodingStrategy = .formatted(formatter)