使用 codable 将字符串转换为 Date/Int/Double

Convert string to Date/Int/Double using codable

我收到 API 的回复,但问题是 API 正在将值作为日期和双精度字符串发回。因此,我收到错误 "Expected to decode Double but found a string/data instead." 我已经像这样构造了我的结构来解决问题,但这似乎是一个补丁。有没有更好的方法来解决这个问题?我觉得苹果已经想到了这一点,并在本地包含了一些东西来解决这个问题。

struct SimpleOrder:Codable{ 
    var createdDate:Date! {
        return createdDateString.dateFromISO8601
    }
    var createdDateString:String

    var orderId:String!

    var priceVal:Double!
    var priceString:String{
        didSet {
            priceVal = Double(self.priceString)!
        }
    }

    private enum CodingKeys: String, CodingKey {
        //case createdDate
        case createdDateString = "time"

        case orderId = "id"

        case priceVal
        case priceString = "price"
    }
}

我不知道这是否相关,但这就是它的使用方式。我将数据作为字符串获取并将其转换为存储在 dataFromString 变量

中的数据
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601 //This is irrelevant though because the date is returned as a string. 

do{
    let beer = try decoder.decode(SimpleOrder.self, from: dataFromString)
    print ("beer is \(beer)")
}catch let error{
    print ("error is \(error)")
}

由于使用了 codable,我在尝试获取 SimpleOrder 的空实例时遇到错误。在我使用 codable 之前,我在没有任何参数的情况下使用 SimpleOrder() 没有任何问题。

错误:无法在没有参数的情况下为类型 'SimpleOrder' 调用初始值设定项

var singlePoint = SimpleOrder()
struct SimpleOrder: Codable {
    var created: Date?
    var orderId: String?
    var price: String?
    private enum CodingKeys: String, CodingKey {
        case created = "time", orderId = "id", price
    }
    init(created: Date? = nil, orderId: String? = nil, price: String? = nil) {
        self.created = created
        self.orderId = orderId
        self.price = price
    }
}

extension SimpleOrder {
    var priceValue: Double? {
        guard let price = price else { return nil }
        return Double(price)
    }
}

extension Formatter {
    static let iso8601: DateFormatter = {
        let formatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
        return formatter
    }()
}

解码 API 返回的 json 数据:

let jsonData = Data("""
{
    "time": "2017-12-01T20:41:48.700Z",
    "id": "0001",
    "price": "9.99"
}
""".utf8)

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(Formatter.iso8601)

do {
    let simpleOrder = try decoder.decode(SimpleOrder.self, from: jsonData)
    print(simpleOrder)
} catch {
    print(error)
}

或者初始化一个没有值的新对象:

var order = SimpleOrder()