在快速JSON对象中将对象数组解析为字符串元素数组

时间:2019-01-28 09:41:19

标签: arrays swift

我正在尝试解析从Web服务接收的JSON对象,该对象将结果作为状态和数据的JSON对象给出。data还是一个对象数组,我想从这个对象中获取一个元素作为基础必须填写表格视图。

Web服务结果如下

{"status":1,"data":[{"service_id":"1","service_name":"Painter"},{"service_id":"2","service_name":"Plumber"},{"service_id":"3","service_name":"Electrician"},{"service_id":"4","service_name":"Handyman"},{"service_id":"5","service_name":"Carpenter"},{"service_id":"6","service_name":"Mason"}]}

我迅速解析为:- 创建了一个班级

class ABC: NSObject {   

    var service_name:String?
    var service_id : Int?

    init(service_name:String,service_id:Int) {
        self.service_name = service_name
        self.service_id = service_id

    }


        let myUrl = URL(string: "services.php");
        var request = URLRequest(url:myUrl!)
        request.httpMethod = "POST"// Compose a query string
        let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
            if error != nil
            {
                print("error=\(String(describing: error))")
                return
            }
            do {
                let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
                if let parseJSON = json
                {
                    let status=parseJSON["status"] as? Int

                    let newdata : NSDictionary = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
                    self.model=(newdata.value(forKey: "data") as? [ABC])!

我的问题是我在self.model中得到一个对象数组作为service_name和service_id键,现在我想取出一个包含所有service_name对象值的字符串数组,这意味着无法将NSArray转换为swift数组。

3 个答案:

答案 0 :(得分:0)

现在随处使用Dictionary的地方都使用本机Swift类型NSDictionary

然后通过在字典的下标中指定键来获得键的特定值

if let model = newData["data"] as? [ABC] {
    self.model = model
}

无论如何,我建议您开始使用Codable而不是JSONSerialization

struct Response: Decodable {
    let status: Int
    let data: [ABC]
}
struct ABC: Decodable {
    let serviceName: String
    let serviceId: String // note that `serviceId` isn’t `Int` But `String`
}

,然后使用JSONDecoder

解码数据
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
    let response = try decoder.decode(Response.self, from: data!)
    self.model = response.data
} catch { print(error) }

答案 1 :(得分:0)

我建议删除JSONSerialization并使用Codable协议代替CodingKeys

这里是一个简单的示例,以了解其工作原理。

struct Service : Codable {
    let id : Int
    let name : String

    // keys
    private enum CodingKeys: String, CodingKey {
        case id = "service_id"
        case name = "service_name"
    }
}

...
// assuming our data comes from server side
let jsonString = "..."
let jsonData = jsonString.data(using: .utf8)!

do {
    let jsonDecoder = JSONDecoder()
    let user = try jsonDecoder.decode(Service.self, from: jsonData)
    print("Getting service: \(service.id) \(service.name)")
} catch {
    print("Unexpected error: \(error).")
}

更多documentation在这里。

答案 2 :(得分:0)

其他人已经提到过使用(De)codable。它易于使用且非常舒适。没有类型转换,也没有文字键。

创建两个结构,将成员声明为具有 camelCased 名称的非可选常量,并省略初始化程序。

struct Root : Decodable {
    let status : Int
    let data : [Service]
}

struct Service : Decodable {
    let serviceName : String
    let serviceId : String
}

然后在另一个类或结构中解码JSON

    let myUrl = URL(string: "services.php")
    var request = URLRequest(url: myUrl!)
    request.httpMethod = "POST"// Compose a query string
    let task = URLSession.shared.dataTask(with: request) { data, _, error in
        if let error = error { print(error); return }

        do {
            let decoder = JSONDecoder()
            decoder.keyDecodingStrategy = .convertFromSnakeCase
            let json = try decoder.decode(Root.self, from: data!)
            let status = json.status
            let newdata = json.data
        } catch { print(error))
    }
    task.resume()
相关问题