我现在正在运行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)
}
}
}
我希望有人可以帮助我,因为我不完全确定这种解析是如何工作的。
答案 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)
你可以修改解码的“评级”结果,这应该很容易。
希望这可以给你一点帮助。 :)