简体   繁体   English

使用Alamofire和SwiftyJSON正确解析带有多个对象的JSON数组

[英]Correctly parsing through a JSON array with multiple objects using Alamofire and SwiftyJSON

I am able to print out the response. 我能够打印出回复。 However I am unable to loop through the array and initialise it. 但是,我无法遍历数组并对其进行初始化。 This is how I am requesting the data: 这就是我请求数据的方式:

Alamofire.request(url, method: .get, parameters: nil, encoding: URLEncoding.default).responseJSON { (response) in

    print(response.value!)

    guard let data = response.data else { return }
    let json = JSON(data: data)

    for r in json.arrayValue {
        let person = Person(json: r)
    }
}

I have added breakpoints but I am unable to understand as to why the loop does not happen? 我添加了断点,但是我无法理解为什么循环不会发生?

Update: 更新:

response.value! example: 例:

{
  "pagination": {
    "object_count": 1,
    "page_number": 1
  },
  "attendees": [
    {
      "id": "818060297",
      "quantity": 1,
      "profile": {
        "first_name": "John",
        "last_name": "Doe",
        "company": "Apple",
        "name": "John Doe",
        "email": "john_doe@testmail.com",
        "job_title": "CEO"
      },
      "status": "Attending"
    }
  ]
}

Update 2 更新2

Here is my AttendeesProfile class: 这是我的AttendeesProfile类:

class AttendeesProfile {

    var name: String?

    init(json: JSON) {
        self.name = json["name"].stringValue
    }

}

Now I am not sure how to get the Attendee class to work properly: 现在,我不确定如何使Attendee类正常工作:

class Attendees {

    var attendees = [String]()
    var attendeesProfile: AttendeesProfile!

    init(json: JSON) {
        // Something here
    }
}

I suspect your guard statement stopping your code flow before you loop through your array : guard let data = response.data else { return } 我怀疑您的guard声明在循环遍历数组之前停止了代码流: guard let data = response.data else { return }

With this line, you are saying if data has something then the code flow can continue. 在此行中,您要说的是如果数据中包含某些内容,则代码流可以继续。 If not, please stop it and return. 如果没有,请停止并返回。 So, you never reach your loop statement. 因此,您永远不会到达循环语句。

Are you sure that your response.data has something and is different from nil ? 您确定您的response.data包含某些内容并且与nil不同吗? Your print(response.value!) shows something ? 您的print(response.value!)显示了什么?

You have to cast your response data. 您必须转换响应数据。 You can not walk on an unknown array I suggest you to use ObjectMapper library. 您不能在未知数组上行走,建议您使用ObjectMapper库。 It can parse your data to your willing model and if received data is nil or is not your wanted model you can find out easily. 它可以将您的数据解析为您愿意的模型,如果收到的数据为零或不是您想要的模型,则可以轻松找到。 Do not forget to print response.data to ensure what data exactly is. 不要忘记打印response.data以确保确切的数据。 https://github.com/Hearst-DD/ObjectMapper https://github.com/Hearst-DD/ObjectMapper

You could implement a couple of structs conforming to Decodable , which among other things would give you the benefit of not relying on SwiftyJSON for your code to work. 您可以实现一些符合Decodable的结构,除其他外,这将给您带来好处,即无需依赖SwiftyJSON即可运行代码。

Going off from the JSON data that you have provided, consider the following three simple structs: 从您提供的JSON数据开始,请考虑以下三个简单结构:

struct AttendeeArray: Decodable {
   let attendees: [Attendee]
}

struct Attendee: Decodable {
   let status: String
   let profile: AttendeeProfile
}

struct AttendeeProfile: Decodable {
   let name: String
   let age: Int
}

Each struct simply contains the variables that you have defined in your JSON object. 每个结构仅包含您在JSON对象中定义的变量。

Using the JSONDecoder you will now be able to decode your JSON data as simple as calling: 现在,使用JSONDecoder您可以像调用以下代码一样简单地解码JSON数据:

do { 
   let array = try JSONDecoder().decode(AttendeeArray.self, from: data)
   // do whatever with your attendees array
} catch {
   // handle error if parsing fails
   print(error)
}

I created a simple Playground where you can test this by adding the code bolow along with the Decodable structs above: 我创建了一个简单的Playground,您可以在其中添加以下代码和下面的Decodable结构来进行测试:

import Foundation

func decodeAttendees(json: String) -> AttendeeArray? {
   guard let data = json.data(using: .utf8) else { return nil }
   do {
       return try JSONDecoder().decode(AttendeeArray.self, from: data)
   } catch {
       print("Error: \(error)")
       return nil
   }
}

let json = """
{
   "attendees": [
       {
           "status": "attending",
           "profile": {
               "name": "Joe",
               "age": 22
           }
       },
       {
           "status": "not attending",
           "profile": {
               "name": "Bob",
               "age": 44
           }
       }
   ],
   "servlet": {
       "servlet-name": "cofaxCDS",
       "servlet-class": "org.cofax.cds.CDSServlet"
   }
}
"""

let arr = decodeAttendees(json: json)
arr?.attendees[0].profile.name //"Joe"
arr?.attendees[1].status //"not attending"

Now, for your current Alamofire completion handler, I'm guessing that it would be as simple to modify it to be something along the lines of: 现在,对于您当前的Alamofire完成处理程序,我猜测将其修改为类似于以下内容的代码将很简单:

Alamofire.request(url, method: .get, parameters: nil, encoding:   URLEncoding.default).responseJSON { (response) in
   guard let data = response.data else { return //remember to error if data is nil }
   do {
      let array = JSONDecoder().decode(AttendeesArray.self, from: data)
      //update your UI to show the array, or pass it on to a completion hanldler
   } catch {
      //handle errors
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM