我的建议是实现init(from:)
并用Regular Exit解析日期字符串
public struct DocumentDate: Decodable {
/// Year component of the date, Integer with no limitation on the range.
public let year: Int
/// Month component of the date, Integer from 1 to 12.
public let month: Int
/// Day component of the date, Integer from 1 to 31.
public let day: Int
public init(from decoder: any Decoder) throws {
let container = try decoder.singleValueContainer()
let dateString = try container.decode(String.self)
guard let match = dateString.wholeMatch(of: /(\d{4})-(\d{2})-(\d{2})/)?.output else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "\(dateString) is not a valid date format")
}
year = Int(match.1)!
month = Int(match.2)!
day = Int(match.3)!
}
}
以及如何使用它的示例
let jsonString = """
{"date":"2012-01-13"}
"""
struct Test: Decodable {
let date: DocumentDate
}
do {
let result = try JSONDecoder().decode(Test.self, from: Data(jsonString.utf8))
print(result)
} catch {
print(error)
}
例如,您甚至可以判断月和日是否在有效范围内
let month = Int(match.2)!
guard (1...12).contains(month) else { throw DecodingError.dataCorruptedError(in: container, debugDescription: "Month value \(month) is out of range") }
self.month = month
另一种方法是创建一个包含ISO8601DateFormatter
的日期并提取所需的日期成分
public struct DocumentDate: Decodable {
/// Year component of the date, Integer with no limitation on the range.
public let year: Int
/// Month component of the date, Integer from 1 to 12.
public let month: Int
/// Day component of the date, Integer from 1 to 31.
public let day: Int
public init(from decoder: any Decoder) throws {
let container = try decoder.singleValueContainer()
let dateString = try container.decode(String.self)
let formatter = ISO8601DateFormatter()
formatter.formatOptions = .withFullDate
guard let date = formatter.date(from: dateString) else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "\(dateString) is not a valid date format")
}
let components = Calendar(identifier: .iso8601).dateComponents([.year, .month, .day], from: date)
year = components.year!
month = components.month!
day = components.day!
}
}