具有多种日期格式的 JSONDecoder?
JSONDecoder with multiple date formats?
我有 2 个来自 api 的日期类型。我需要一起解码。但我没有找到任何解决方案。我需要在此代码中添加 "yyyy-MM-dd'T'HH:mm:ssZ"
格式。我该怎么做?
func run<T: Decodable>(_ request: URLRequest, _ decoder: JSONDecoder = JSONDecoder()) -> AnyPublisher<Response<T>, Error> {
return URLSession.shared
.dataTaskPublisher(for: request)
.receive(on: DispatchQueue.main)
.tryMap { result -> Response<T> in
self.dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
decoder.dateDecodingStrategy = .formatted(self.dateFormatter)
let value = try decoder.decode(T.self, from: result.data)
return Response(value: value, response: result.response)
}
.eraseToAnyPublisher()
}
您可以通过实现 init(from decoder: Decoder)
来实现自定义解码行为
另一种方法是使用 ISO8601DateFormatter
的自定义 dateDecodingStrategy
,它能够根据给定的字符串
指定日期格式
func run<T: Decodable>(_ request: URLRequest, _ decoder: JSONDecoder = JSONDecoder()) -> AnyPublisher<Response<T>, Error> {
return URLSession.shared
.dataTaskPublisher(for: request)
.receive(on: DispatchQueue.main)
.tryMap { result -> Response<T> in
decoder.dateDecodingStrategy = .custom { decoder -> Date in
let container = try decoder.singleValueContainer()
let dateFormatter = ISO8601DateFormatter()
let dateString = try container.decode(String.self)
if !dateString.hasSuffix("Z") {
dateFormatter.formatOptions.remove(.withTimeZone)
}
if let isoDate = dateFormatter.date(from: dateString) {
return isoDate
} else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Wrong Date Format")
}
}
let value = try decoder.decode(T.self, from: result.data)
return Response(value: value, response: result.response)
}
.eraseToAnyPublisher()
}
我有 2 个来自 api 的日期类型。我需要一起解码。但我没有找到任何解决方案。我需要在此代码中添加 "yyyy-MM-dd'T'HH:mm:ssZ"
格式。我该怎么做?
func run<T: Decodable>(_ request: URLRequest, _ decoder: JSONDecoder = JSONDecoder()) -> AnyPublisher<Response<T>, Error> {
return URLSession.shared
.dataTaskPublisher(for: request)
.receive(on: DispatchQueue.main)
.tryMap { result -> Response<T> in
self.dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
decoder.dateDecodingStrategy = .formatted(self.dateFormatter)
let value = try decoder.decode(T.self, from: result.data)
return Response(value: value, response: result.response)
}
.eraseToAnyPublisher()
}
您可以通过实现 init(from decoder: Decoder)
另一种方法是使用 ISO8601DateFormatter
的自定义 dateDecodingStrategy
,它能够根据给定的字符串
func run<T: Decodable>(_ request: URLRequest, _ decoder: JSONDecoder = JSONDecoder()) -> AnyPublisher<Response<T>, Error> {
return URLSession.shared
.dataTaskPublisher(for: request)
.receive(on: DispatchQueue.main)
.tryMap { result -> Response<T> in
decoder.dateDecodingStrategy = .custom { decoder -> Date in
let container = try decoder.singleValueContainer()
let dateFormatter = ISO8601DateFormatter()
let dateString = try container.decode(String.self)
if !dateString.hasSuffix("Z") {
dateFormatter.formatOptions.remove(.withTimeZone)
}
if let isoDate = dateFormatter.date(from: dateString) {
return isoDate
} else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Wrong Date Format")
}
}
let value = try decoder.decode(T.self, from: result.data)
return Response(value: value, response: result.response)
}
.eraseToAnyPublisher()
}