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

时间:2018-06-04 15:26:40

标签: swift api swift4 codable

我现在正在运行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)
        }
    }
}

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

1 个答案:

答案 0 :(得分:3)

你可以实现自己的解码init方法,从解码容器中获取每个类属性,在本节中,让你的逻辑处理更好的“rating”是一个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)
  • 如果评级API的值是普通字符串,您可以按照自己的意愿获得它。
  • 如果评级API的值为0,则评级将等于“评级为零或0”
  • 如果评级API的值是其他整数,则评级将是“评级为整数但不是0”

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

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

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