如何解决如何从 URLSession 解码 http 响应数据并快速映射到响应结构 注意事项更好的代码
我是 swift 编程的新手..能够从 URLSession 获得成功的响应,但我无法将数据对象解析(解码)为我想要的 APIResponse 结构
这是我的网址请求代码:
func load(urlRequest: URLRequest,withCompletion completion: @escaping (_ response: APIResponse) -> Void) {
let task = URLSession.shared.dataTask(with: urlRequest) { (data,response,error) in
guard error == nil else {
print("Error fetching data from server\nERROR: \(String(describing: error))")
return
}
guard let jsonData = data else {
print("Response Data is empty")
return
}
printResponseBody(response: data)
let decoder = JSONDecoder()
let response = try? decoder.decode(APIResponse.self,from: jsonData)
guard let decodedResponse = response else {
print("Unable to parse data from response")
return
}
print("Decoded Response: ",decodedResponse)
DispatchQueue.main.async { completion(decodedResponse) }
}
task.resume()
}
这是我的响应结构,我需要将响应数据映射到以在我的代码中使用:
struct APIResponse: Codable {
let responseCode: Int
let data: ResultSet
let meta: Meta
enum CodingKeys: String,CodingKey {
case responseCode = "response_code"
case data,meta
}
}
// MARK: - DataClass
struct ResultSet: Codable {
let appVersionUpdate: String
let offers: [Offer]
let rate: Int
enum CodingKeys: String,CodingKey {
case appVersionUpdate = "app_version_update"
case offers,rate
}
}
// MARK: - Offer
struct Offer: Codable,Identifiable {
let id: Int
let title: String
let image: String?
let r,resultCount: Double
enum CodingKeys: String,CodingKey {
case id,r = "r"
case title,image
case resultCount = "result_count"
}
}
// MARK: - Meta
struct Meta: Codable {
let apiVersion: Int
enum CodingKeys: String,CodingKey {
case apiVersion = "api_version"
}
这是我试图解码的来自服务器的 json
{
"response_code": 0,"data": {
"app_version_update": "","offers": [
{
"title": "Special Scheme1","image": "http://59.145.109.138:11101/Offers/BGL_banner_1080_x_540_1.jpg","r": 1.0,"result_count": 5.0
},{
"title": "test 1","image": "http://59.145.109.138:11101/Offers/Yoho-National-Park2018-10-27_10-10-52-11.jpg","r": 2.0,{
"title": "Offer Test 1234444","image": "http://59.145.109.138:11101/Offers/Stanley-Park2018-10-27_10-11-27-44.jpg","r": 3.0,"result_count": 5.0
}
],"rate": 2000
},"meta": {
"api_version": 2.0
}
}
每当我运行此代码时,我都会收到“无法从响应解析数据”错误。如果有人告诉我我在这里做错了什么,我将不胜感激
解决方法
问题在于解码 id
中的 Offer
。将您的 Offer
替换为:
struct Offer: Codable,Identifiable {
let id: Int
let title: String
let image: String?
let r,resultCount: Int
enum CodingKeys: CodingKey {
case id,r,title,image,resultCount
var stringValue: String {
switch self {
case .id,.r: return "r"
case .title: return "title"
case .image: return "image"
case .resultCount: return "result_count"
}
}
}
}
注意事项
- 首先,您不应该摆脱错误。相反,您可以打印错误并尝试找出问题所在。
- 如果您声明
enum CodingKeys: String,CodingKey
,则每个 case 的原始值必须与另一个不同,否则 Xcode 会报错。在您的情况下,它没有抱怨,因为id
是Identifiable
协议的要求,但它甚至没有使用您为id
设置的原始值。如果你想对 2 个不同的变量使用相同的键,你应该做我上面做的同样的事情。
更好的代码
这与您的代码的工作方式相同,但更简洁:
struct Offer: Codable,Identifiable {
var id: Int { r }
let title: String
let image: String?
let r,resultCount: Int
enum CodingKeys: String,CodingKey {
case r,resultCount
}
}
它基本上是说每次你需要 id
时,从 r
获取它。您也可以像我一样删除 stringValue
中的 CodingKeys
,并使用 CodingKeys: String
构造。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。