使用可编码的

时间:2017-12-01 19:48:17

标签: json swift swift4 codable

我从API获得响应,但问题是API正在将值作为一串日期和双精度发回。因此我得到了错误"预计会解码Double但却找到了一个字符串/数据。"我已经构建了这样的结构来解决问题,但这似乎是一个补丁。有没有更好的方法来解决这个问题?我觉得苹果已经想到了这一点,并包含一些原生的东西来解决这个问题。

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()

1 个答案:

答案 0 :(得分:7)

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()