如何解码URLSession中的http响应数据并迅速映射到响应结构



我是swift编程的新手。。能够从URLSession获得成功的响应,但我无法将数据对象解析(解码(为我想要的APIResponse Structure

这是我的url请求代码:

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 servernERROR: (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,
"result_count": 5.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
}
}

每当我运行此代码时;无法解析来自响应"的数据;错误如果有人告诉我在这里做错了什么,我会非常感激

问题在于解码Offer中的id。将您的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,则每个情况的原始值必须与其他情况不同,否则Xcode将抱怨。在您的情况下,它没有抱怨,因为idIdentifiable协议的要求,但它甚至没有使用您为id设置的原始值。如果你想对两个不同的变量使用相同的键,你应该做我上面做的同样的事情

更好的代码

这将和您的代码一样工作,但更干净:

struct Offer: Codable, Identifiable {

var id: Int { r }
let title: String
let image: String?
let r, resultCount: Int
enum CodingKeys: String, CodingKey {
case r, title, image, resultCount
}
}

它基本上说,每次你需要id,就从r那里得到。你也可以像我一样去除CodingKeys中的stringValue,并使用CodingKeys: String构象。

最新更新