动态更改API数据提取结构

时间:2018-01-18 10:50:01

标签: ios swift api struct

我从API获取数据,该数据每天都会从StringDouble不定期地多次更改格式。

是否可以对struct执行某些操作以防止在提取时返回nil并使用正确的类型自动使用?

    struct BitcoinGBP : Decodable {
    let price : Double
    let percentChange24h : Double

    private enum CodingKeys : String, CodingKey {
        case price = "PRICE"
        case percentChange24h = "CHANGEPCT24HOUR"
    }
}

只需使用Double?吗?

2 个答案:

答案 0 :(得分:0)

编写自定义初始化程序以处理这两种情况

struct BitcoinGBP : Decodable {
    let price : Double
    let percentChange24h : Double

    private enum CodingKeys : String, CodingKey {
        case price = "PRICE"
        case percentChange24h = "CHANGEPCT24HOUR"
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        percentChange24h = try container.decode(Double.self, forKey: .percentChange24h)
        do {
            price = try container.decode(Double.self, forKey: .price)
        } catch DecodingError.typeMismatch(_, _) {
            let stringValue = try container.decode(String.self, forKey: .price)
            price = Double(stringValue)!
        }
    }
}

答案 1 :(得分:0)

根据我的经验,您需要设计您的结构,模型以符合您期望在应用程序中使用的内容,而不是API将为您提供的内容。您需要为API做好准备,以便为您提供不正确的数据类型或缺少奇怪的数据。

如果API变化太大,则用户需要更新,但通常不会这样做。端点必须具有版本,并且在产生巨大差异时需要更改版本。如果不是这种情况,它是有缺陷的API(这些事情仍然会发生),在这种情况下你应该使用自己的服务器,代理连接到所需的服务器并修改他们自己的API。您对其进行了一些测试,以检测其API是否已更改并尽快修改自己的API,以便所有应用程序仍然可以连接到它。但这超出了这个问题的范围。

如果您的结构必须在24小时内有价格和百分比变化,而两者都是双倍,那么只需要来自API的字符串或任何内容。我喜欢避免任何自动执行此操作的工具,因此我只使用便利构造函数和我自己的一组工具来生成类似的东西:

class BitcoinGBP {

    var price: Double = 0.0
    var priceChange24h: Double = 0.0

    convenience init(price: Double, priceChange24h: Double) {
        self.init()
        self.price = price
        self.priceChange24h = priceChange24h
    }

    /// Construuctor designed to accept JSON formated dictionary
    ///
    /// - Parameter descriptor: A JSON descriptor
    convenience init(descriptor: [String: Any]) {
        self.init()
        self.price = double(value: descriptor["PRICE"]) ?? 0.0
        self.priceChange24h = double(value: descriptor["CHANGEPCT24HOUR"]) ?? 0.0
    }

    /// A conveninece method to extract a double value
    ///
    /// - Parameter value: A value to be converted
    /// - Returns: Double value if possible
    func double(value: Any?) -> Double? {
        if let value = value as? String {
            return Double(value)
        } else if let value = value as? Double {
            return value
        } else if let value = value as? Float {
            return Double(value)
        } else if let value = value as? Int {
            return Double(value)
        } else if let value = value as? Bool {
            return value ? 1.0 : 0.0
        } else {
            return nil
        }
    }
}

现在剩下的就是取决于你需要什么功能。