如何将Alamofire与Codable协议一起使用并解析数据



使用Codable协议的时间,所以很多事情都不清楚。在经历了几个教程之后,从可编码的东西开始解析数据。下面是代码:

struct MyTasks : Codable {
var strDateDay : String = ""
var strReminder : String = ""
var strRepetitions : String = ""
var name : String = ""
var strNotes : String = ""
var strUserId : String = ""
private enum CodingKeys: String, CodingKey {
case strDateDay = "duedate"
case strReminder = "reminder"
case strRepetitions = "recurring"
case name = "name"
case strNotes = "notes"
case strUserId = "userId"
}
}
let networkManager = DataManager()
networkManager.postLogin(urlString: kGetMyTasks, header: header, jsonString: parameters as [String : AnyObject]) { (getMyTasks) in
print(getMyTasks?.name as Any) // -> for log
Common_Methods.hideHUD(view: self.view)
}

网络管理器:

func postLogin(urlString: String, header: HTTPHeaders, jsonString:[String: AnyObject], completion: @escaping (MyTasks?) -> Void) {
let apiString = KbaseURl + (kGetMyTasks as String)
print(apiString)
Alamofire.request(apiString, method: .post, parameters: jsonString , encoding: URLEncoding.default, headers:header).responseJSON
{ response in
let topVC = UIApplication.shared.keyWindow?.rootViewController
DispatchQueue.main.async {
//Common_Methods.showHUD(view: (topVC?.view)!)
}
guard let data = response.data else { return }
do {
let decoder = JSONDecoder()
let loginRequest = try decoder.decode(MyTasks.self, from: data)
completion(loginRequest)
} catch let error {
print(error)
completion(nil)
}
}
}

现在,这是响应:

keyNotFound(CodingKeys(stringValue: "strDateDay", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: "strDateDay", intValue: nil) ("strDateDay").", underlyingError: nil))

以下是我尝试解析的 json 响应:

{
"data": [
{
"userId": 126,
"name": "My task from postman ",
"notes": null,
"totalSteps": 0,
"completedSteps": 0,
"files": 0
},
{
"userId": 126,
"name": "My task from postman 1",
"notes": null,
"totalSteps": 0,
"completedSteps": 0,
"files": 0
}
]   
} 

我知道我错过了一些东西,但即使花了半天多的时间,我也没有正确理解出了什么问题以及在哪里。请指导。

问题在于您的结构,结构中的属性名称应与 JSON 数据匹配,或者如果要使用自定义名称,则应使用enum CodingKeys将它们转换为您喜欢的

struct MyTasks: Codable {
let data: [Datum]
}
struct Datum: Codable {
let userID: Int?
let name: String
let notes: String?
let totalSteps, completedSteps, files: Int
enum CodingKeys: String, CodingKey {
case userID = "userId"
case name, notes, totalSteps, completedSteps, files
}
}
func postLogin(urlString: String, header: HTTPHeaders, jsonString:[String: AnyObject], completion: @escaping (MyTasks?) -> Void) {
let apiString = KbaseURl + (kGetMyTasks as String)
print(apiString)
Alamofire.request(apiString, method: .post, parameters: jsonString , encoding: URLEncoding.default, headers:header).responseJSON
{ response in
let topVC = UIApplication.shared.keyWindow?.rootViewController
DispatchQueue.main.async {
//Common_Methods.showHUD(view: (topVC?.view)!)
}
guard let data = response.data else { return }
do {
let decoder = JSONDecoder()
let loginRequest = try decoder.decode(MyTasks.self, from: data)
completion(loginRequest)
} catch let error {
print(error)
completion(nil)
}
}
}

还有一件事请记住,您知道notes的确切类型并使其成为可选的,否则它会引发错误,没有类型,所以我在那里放了一个可选的字符串。

希望这会有所帮助。

问题是在你的顶级 JSON 中,你有一个类型array的"数据"属性。

您要求 JSONDecoder 将仅包含"data"属性的 JSON 对象解码为名为"MyTasks"的 Swift 对象,其中包含您定义的存储属性(包括 strDateDay(。

因此,解码器会向您发送此响应,因为他无法在该顶部对象中找到 strDateDay。

您必须创建一个用于反序列化的顶级对象。像这样:

struct MyResponse: Codable {
var data: [MyTasks]
}

然后就像你已经做的那样把它交给你的 JSONDecoder:

let loginRequest = try decoder.decode(MyResponse.self, from: data)

您发送到解码器的数据是完整的JSON流(Alamofire响应对象的数据属性(,而不仅仅是JSON结构的"data"属性。

我建议使用CodyFire库,因为它支持Codable与请求相关的所有内容。

您的 POST 请求可能看起来像

struct MyTasksPayload: JSONPayload {
let param1: String
let param2: String
}
struct MyTasksResponseModel: Codable {
let strDateDay: String
let strReminder: String
let strRepetitions: String
let name: String
}
let server = ServerURL(base: "https://server1.com", path: "v1")
APIRequest<[MyTasksResponseModel]>(server, "mytasks", payload: payloadModel)
.method(.post)
.onRequestStarted {
// show HUD here
}
.onError {
// hide hud and show error here
}
.onSuccess { tasks in
// here's your decoded tasks
// hide hud here
}

使用APIRequest<[MyTasksResponseModel]>解码数组

使用 APIRequest 解码一个对象

最新更新