可编码:将字符串解码为自定义类型(ISO 8601 日期,无时间组件)

问题描述 投票:0回答:1

考虑以下类型:

public struct DocumentDate: Codable {
    /// 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
}

Codable
更具体地说
Decodable
协议支持合并到此类型中以解码 ISO 8601 兼容日期类型的最简单方法是什么:

"2012-01-13"

理想情况下,我希望在初始化程序中得到一个

String
解码,然后我就可以按照我的意愿解析它。实施这种支持的最佳策略是什么?

我知道我可以使用 dateDecodingStrategy 但这是将

String
解码为
Date
。我的类型实际上不是
Date
,而是自定义类型,所以这就是挑战所在。

swift date codable iso8601 decodable
1个回答
0
投票

我的建议是实现

init(from:)
并使用正则表达式解析日期字符串

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: "Wrong 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)
}
© www.soinside.com 2019 - 2024. All rights reserved.