Swift 正在获取自定义类型的日期()
我有一个服务器API,它为JSON提供两种不同格式的日期——一种结构嵌套在另一种结构中 我的Swift应用程序使用Swift Codable解码JSON,因此我需要添加一些特殊处理,以允许解码两种自定义日期格式 很容易,我发现这可以在一个结构中处理不同的格式Swift 正在获取自定义类型的日期(),swift,Swift,我有一个服务器API,它为JSON提供两种不同格式的日期——一种结构嵌套在另一种结构中 我的Swift应用程序使用Swift Codable解码JSON,因此我需要添加一些特殊处理,以允许解码两种自定义日期格式 很容易,我发现这可以在一个结构中处理不同的格式 struct FirstModel: Codable, Identifiable { var id: Int? let second: SecondModel let date: CustomDate<Firs
struct FirstModel: Codable, Identifiable {
var id: Int?
let second: SecondModel
let date: CustomDate<First>
...
}
struct SecondModel: Codable, Identifiable {
var id: Int?
let date: CustomDate<Second>
...
}
编译器给出了错误
无法将“Date”类型的值转换为“Date”参数的预期参数类型“CustomDate”。
我知道CustomDate(xxx)是一个DateFormatter,所以不是一个日期类型,但我甚至不知道从哪里开始获取该“类型”的新日期对象。请有人帮助以Swift编译器可以接受的方式传递当前日期的语法。谢谢
另外,我还怀疑我在某个时候需要一个“设置”编码器,对吗
更新
按照下面Joakim的建议,再加上编译器建议的修复,我尝试了
let date = try! CustomDate<First>(from: Date() as! Decoder)
let date=试试看!CustomDate(from:Date()作为!解码器)
…进行编译,但在运行时崩溃,并出现错误
无法将“Foundation.Date”类型的值强制转换为“Swift.Decoder”。您可以创建一个自定义解码策略,在出现故障时可以返回到第二个日期格式。如果需要按照相同的规则对自定义结构进行编码,则还需要提供自定义编码方法: 首先创建日期格式化程序
extension Formatter {
static let customUK: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_UK")
formatter.dateFormat = "E, d MMM yyyy HH:mm zzz"
return formatter
}()
static let yyyyMMdd: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_UK")
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
}
然后你的自定义日期解码策略
extension JSONDecoder.DateDecodingStrategy {
static let customUK = custom {
let container = try $0.singleValueContainer()
let string = try container.decode(String.self)
guard
let date = Formatter.customUK.date(from: string) ??
Formatter.yyyyMMdd.date(from: string) else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid date: \(string)")
}
return date
}
}
您的自定义编码策略也是如此
extension JSONEncoder.DateEncodingStrategy {
static let customUK = custom {
var container = $1.singleValueContainer()
try container.encode(Formatter.customUK.string(from: $0))
}
}
如果需要确保按照原始日期格式对子结构进行编码,则需要为其提供自己的编码方法:
struct First: Codable {
var id: Int?
let second: Second
let date: Date
init(id: Int?, date: Date = Date(), second: Second) {
self.id = id
self.date = date
self.second = second
}
}
操场测试:
let first = First(id: 1, second: .init(id: 2))
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .customUK
let data = try! encoder.encode(first)
print(String(data: data, encoding: .utf8)!) // {"id":1,"second":{"id":2,"date":"2020-06-02"},"date":"Tue, 2 Jun 2020 16:31 GMT-3"}
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .customUK
let firstDecoded = try! decoder.decode(First.self, from: data)
print(firstDecoded) // "First(id: Optional(1), second: __lldb_expr_227.Second(id: Optional(2), date: 2020-06-02 03:00:00 +0000), date: 2020-06-02 19:38:00 +0000)\n"
let first=FirstModel(id:nil,date:CustomDate(value:date())
谢谢@JoakimDanielson,但不幸的是,这也无法编译。编译器错误是“参数类型”Date不符合预期类型“解码器”和“调用中的参数标签不正确(具有“值:”,预期为“发件人:”)”对不起,我的错误。由于您已经实现了一个init,因此不再创建合成的init,因此在代码中手动创建对象时,您需要CustomDate使用一个新的init。是的,但是如果需要,您可以更改签名,但基本上是一个init,它以日期
作为参数,并将其分配给值
property@Snips查看我下面的帖子
struct First: Codable {
var id: Int?
let second: Second
let date: Date
init(id: Int?, date: Date = Date(), second: Second) {
self.id = id
self.date = date
self.second = second
}
}
struct Second: Decodable {
var id: Int?
let date: Date
init(id: Int?, date: Date = Date()) {
self.id = id
self.date = date
}
}
extension Second: Encodable {
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(Formatter.yyyyMMdd.string(for: date), forKey: .date)
}
}
let first = First(id: 1, second: .init(id: 2))
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .customUK
let data = try! encoder.encode(first)
print(String(data: data, encoding: .utf8)!) // {"id":1,"second":{"id":2,"date":"2020-06-02"},"date":"Tue, 2 Jun 2020 16:31 GMT-3"}
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .customUK
let firstDecoded = try! decoder.decode(First.self, from: data)
print(firstDecoded) // "First(id: Optional(1), second: __lldb_expr_227.Second(id: Optional(2), date: 2020-06-02 03:00:00 +0000), date: 2020-06-02 19:38:00 +0000)\n"