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

时间:2017-11-13 16:49:24

标签: ios swift alamofire swifty-json

我能够打印出回复。但是我无法遍历数组并初始化它。这就是我请求数据的方式:

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)
    }
}

我添加了断点,但我无法理解为什么循环不会发生?

更新

response.value!示例:

{
  "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"
    }
  ]
}

更新2

这是我的AttendeesProfile类:

class AttendeesProfile {

    var name: String?

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

}

现在我不确定如何让Attendee课程正常工作:

class Attendees {

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

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

3 个答案:

答案 0 :(得分:0)

我怀疑您的guard let data = response.data else { return }语句会在循环播放数组之前停止代码流:response.data

有了这一行,你就是说数据是否有东西,那么代码流就可以继续了。如果没有,请停止并返回。所以,你永远不会达到循环语句。

你确定你的print(response.value!)有什么不同之处吗?你的{{1}}显示了什么?

答案 1 :(得分:0)

您必须投射您的回复数据。你不能走在一个未知的阵列上 我建议你使用ObjectMapper库。它可以将您的数据解析为您愿意的模型,如果收到的数据为零或不是您想要的模型,您可以轻松找到。不要忘记打印response.data以确保确切的数据。 https://github.com/Hearst-DD/ObjectMapper

答案 2 :(得分:0)

您可以实现一些符合Decodable的结构,除了其他功能之外,它还可以让您不依赖SwiftyJSON来使代码生效。

从您提供的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
}

每个结构只包含您在JSON对象中定义的变量。

使用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)
}

我创建了一个简单的Playground,你可以通过添加代码bolow和上面的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"

现在,对于您当前的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
   }
}