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

Nxt*_*t97 8 api swift swift4 codable

我现在正在运行 Codables。但 API 有一些字符串条目,如果它们为空,有时可能会出现Int值。0我在这里搜索并发现了这个:Swift 4 Codable - Bool or String Values但我无法让它运行

我的结构

struct check : Codable {
    let test : Int
    let rating : String?  
}
Run Code Online (Sandbox Code Playgroud)

评级大多数时候是这样的"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()
}
Run Code Online (Sandbox Code Playgroud)

加载它:

func loadStars() {
    checkStar(for: 1) { (result) in
        switch result {
        case .success(let goo):
            dump(goo)
        case .failure(let error):
            fatalError(error.localizedDescription)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

小智 5

您可以实现自己的解码初始化方法,从解码容器中获取每个类属性,在本节中,使您的逻辑处理“评级”是 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)
Run Code Online (Sandbox Code Playgroud)
  • 如果评级API的值为普通字符串,您将得到您想要的结果。
  • 如果评级 API 的值为 0,则评级将等于“评级为 nil 或 0”
  • 如果评级API的值为其他整数,则评级将为“评级为整数但不为0”

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

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

欲了解更多信息:Apple的编码和解码文档