Swift 4 Codable - API 有时提供 Int 有时提供 String

Posted

技术标签:

【中文标题】Swift 4 Codable - API 有时提供 Int 有时提供 String【英文标题】:Swift 4 Codable - API provides sometimes an Int sometimes a String 【发布时间】:2018-06-04 15:26:40 【问题描述】:

我现在正在运行 Codables。但是 API 有一些 String 条目,如果它们为空,则有时它们的 Int 值为 0。我在这里搜索并找到了这个:Swift 4 Codable - Bool or String values 但我无法让它运行

我的结构

struct check : Codable 
    let test : Int
    let rating : String?  

评分通常类似于"1Star"。但如果没有评分,我会得到 0 作为 Int 回复。

我正在解析这样的数据:

enum Result<Value> 
    case success(Value)
    case failure(Error)


func checkStar(for userId: Int, completion: ((Result<check>) -> Void)?) 
    var urlComponents = URLComponents()
    urlComponents.scheme = "https"
    urlComponents.host = "xyz.com"
    urlComponents.path = "/api/stars"
    let userIdItem = URLQueryItem(name: "userId", value: "\(userId)")
    urlComponents.queryItems = [userIdItem]
    guard let url = urlComponents.url else  fatalError("Could not create URL from components") 

    var request = URLRequest(url: url)
    request.httpMethod = "GET"


    let config = URLSessionConfiguration.default
    config.httpAdditionalHeaders = [
        "Authorization": "Bearer \(keytoken)"
    ]

    let session = URLSession(configuration: config)
    let task = session.dataTask(with: request)  (responseData, response, responseError) in
        DispatchQueue.main.async 
            if let error = responseError 
                completion?(.failure(error))
             else if let jsonData = responseData 
                // Now we have jsonData, Data representation of the JSON returned to us
                // from our URLRequest...

                // Create an instance of JSONDecoder to decode the JSON data to our
                // Codable struct
                let decoder = JSONDecoder()

                do 
                    // We would use Post.self for JSON representing a single Post
                    // object, and [Post].self for JSON representing an array of
                    // Post objects
                    let posts = try decoder.decode(check.self, from: jsonData)
                    completion?(.success(posts))
                 catch 
                    completion?(.failure(error))
                
             else 
                let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey : "Data was not retrieved from request"]) as Error
                completion?(.failure(error))
            
        
    

    task.resume()

正在加载:

func loadStars() 
    checkStar(for: 1)  (result) in
        switch result 
        case .success(let goo):
            dump(goo)
        case .failure(let error):
            fatalError(error.localizedDescription)
        
    

我希望有人可以帮助我,因为我不完全确定这种解析等是如何工作的。

【问题讨论】:

您链接到您需要的解决方案,但您发布的代码显示没有尝试使用该解决方案。你尝试了什么?您需要自定义init(from:),就像您链接的问题的答案一样。 【参考方案1】:

您可以实现自己的 decode init 方法,从 decode 容器中获取每个类属性,在本节中,让您的逻辑处理“评级”是 Int 还是 String,最后对所有必需的类属性进行签名。

这是我做的一个简单的演示:

class Demo: Decodable 
    var test = 0
    var rating: String?

    enum CodingKeys: String, CodingKey 
        case test
        case rating
    

    required init(from decoder: Decoder) throws 
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let test = try container.decode(Int.self, forKey: .test)
        let ratingString = try? container.decode(String.self, forKey: .rating)
        let ratingInt = try? container.decode(Int.self, forKey: .rating)
        self.rating = ratingString ?? (ratingInt == 0 ? "rating is nil or 0" : "rating is integer but not 0")
        self.test = test
    


let jsonDecoder = JSONDecoder()
let result = try! jsonDecoder.decode(Demo.self, from: YOUR-JSON-DATA)
如果 rating API 的值是普通字符串,你会得到你想要的。 如果 rating API 的值为 0,则 rating 将等于“rating is nil or 0” 如果 rating API 的值为其他整数,则 rating 将为“rating is integer but not 0”

您可以修改解码后的“评分”结果,这应该很容易。

希望这能给你一点帮助。 :)

更多信息:Apple's encoding and decoding doc

【讨论】:

self.test = test doing 行是什么? @Nxt97 它将本地 test 变量的值分配给 test 属性。 self.test 是类中的 test 属性。 哦,我的错...我尝试而不是 self.test = test 来做类似 self.rating = rating 的事情,因为我的 Codable 更大而且已经很晚了.. 但是现在一切正常!!!!谢谢你的帮助@vg0x00 你太棒了!

以上是关于Swift 4 Codable - API 有时提供 Int 有时提供 String的主要内容,如果未能解决你的问题,请参考以下文章

Swift Codable:如果 API 将来可能向响应 JSON 添加更多属性,则包括枚举编码键

如何从 iOS Swift Codable 中的 API 响应通知或打印模型类上缺少的密钥?

用 Codable,swift 4 解析 JSON

Xcode 9.3(Swift 4.1)中的 Codable '没有初始化器'

如何在 swift 4 Codable 中手动解码数组?

如何使用 Codable 在 Swift 中使用动态文件名解析 JSON