парсинг массива объектов в массив строковых элементов в быстром JSON-объекте - PullRequest
0 голосов
/ 28 января 2019

Я пытаюсь проанализировать объект JSON, полученный от веб-службы, который дает результат как объект статуса JSON, и data.data снова является массивом объектов, из этого объекта я хочу взять один элемент, на основе которого яЯ должен заполнить таблицу.

Результаты веб-службы представлены как

{"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 голосов
/ 28 января 2019

Я бы порекомендовал сбросить 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).")
}

Подробнее документация здесь.

0 голосов
/ 28 января 2019

Как уже упоминалось другими, используйте (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()
0 голосов
/ 28 января 2019

Используйте собственный тип Swift Dictionary везде, где вы используете 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) }
...