создание объектов из ответа json с использованием NSJSONSerialization

Используя swift 1.2, xcode 6.3 и IOS 8, я пытаюсь создать объект из ответа json, используя класс NSJSONSerialization. ответ json:

[{
  "_id" : "5470def9e0c0be27780121d7",
  "imageUrl" : "https:\/\/s3-eu-west-1.amazonaws.com\/myapi-static\/clubs\/5470def9e0c0be27780121d7_180.png",
  "name" : "Mondo",
  "hasVip" : false,
  "location" : {
    "city" : "Madrid"
  }
}, {
  "_id" : "540b2ff281b30f3504a1c72f",
  "imageUrl" : "https:\/\/s3-eu-west-1.amazonaws.com\/myapi-static\/clubs\/540b2ff281b30f3504a1c72f_180.png",
  "name" : "Teatro Kapital",
  "hasVip" : false,
  "location" : {
    "address" : "Atocha, 125",
    "city" : "Madrid"
  }
}, {
  "_id" : "540cd44581b30f3504a1c73b",
  "imageUrl" : "https:\/\/s3-eu-west-1.amazonaws.com\/myapi-static\/clubs\/540cd44581b30f3504a1c73b_180.png",
  "name" : "Charada",
  "hasVip" : false,
  "location" : {
    "address" : "La Bola, 13",
    "city" : "Madrid"
  }
}]

the object class (Club.swift) with the NSJSONSerialization.JSONObjectWithData implementation is:

class Club: NSObject {

    var id: String = ""
    var name: String = ""
    var imageUrl: String = ""
    var hasVip: Bool = false
    var desc: String = ""
    var location: [Location] = []

    init(JSONString: String) {

        super.init()

        var error : NSError?
        let JSONData = JSONString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)

        let JSONDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(JSONData!, options: nil, error: &error) as! NSDictionary

        self.setValuesForKeysWithDictionary(JSONDictionary as [NSObject : AnyObject])

    }

}

and finally the ApiClient class is

class ApiClient {
    func getList(completionHandler: ([JSON]) -> ()) {
        let URL = NSURL(string: "https://myapi.com/v1/clubs")
        let mutableURLRequest = NSMutableURLRequest(URL: URL!)

        mutableURLRequest.setValue("Content-Type", forHTTPHeaderField: "application/json")
        mutableURLRequest.HTTPMethod = "GET"
        mutableURLRequest.setValue("Bearer R01.iNsG3xjv/r1LDkhkGOANPv53xqUFDkPM0en5LIDxx875fBjdUZLn1jtUlKVJqVjsNwDe1Oqu2WuzjpaYbiWWhw==", forHTTPHeaderField: "Authorization")

        let manager = Alamofire.Manager.sharedInstance
        let request = manager.request(mutableURLRequest)

        request.responseJSON { (request, response, json , error) in
            if (json != nil){
                var jsonObj = JSON(json!)
                if let data = jsonObj["hits"].arrayValue as [JSON]?{

                    var aClub : Club = Club(JSONString: data)

                    println(aClub.name)

                    completionHandler(data)
                }
            }
        }
    }
}

but the problem is when I try to println(aClub.name) the error is

"невозможно вызвать инициализатор для типа "Club" со списком аргументов типа (JSONString [JSON])"

Я не знаю, как я могу использовать класс NSJSONSerialization со сложным ответом JSON.


person Edu    schedule 27.04.2015    source источник


Ответы (1)


jsonObj выглядит как объект SwiftyJSON или что-то в этом роде, который используется вместо NSJSONSerialization, не в связке с ним. Переменная data представляет собой массив объектов JSON (т. е. это [JSON]), а не строку.

Но вы используете метод responseJSON Alamofire, который выполняет синтаксический анализ JSON за вас. Так что вам не нужно использовать ни NSJSONSerialization, ни SwiftyJSON. Он уже разобрал его на массив словарей.

Если вам нужен массив объектов Club, вы можете просто выполнить итерацию по этому массиву, создавая объекты Club из словарей:

class ApiClient {
    func getList(completionHandler: ([Club]?, NSError?) -> ()) {
        let URL = NSURL(string: "https://myapi.com/v1/clubs")
        let mutableURLRequest = NSMutableURLRequest(URL: URL!)

        mutableURLRequest.setValue("Content-Type", forHTTPHeaderField: "application/json")
        mutableURLRequest.HTTPMethod = "GET"
        mutableURLRequest.setValue("Bearer R01.iNsG3xjv/r1LDkhkGOANPv53xqUFDkPM0en5LIDxx875fBjdUZLn1jtUlKVJqVjsNwDe1Oqu2WuzjpaYbiWWhw==", forHTTPHeaderField: "Authorization")

        let manager = Alamofire.Manager.sharedInstance
        let request = manager.request(mutableURLRequest)

        request.responseJSON { (request, response, json, error) in
            var clubs = [Club]()
            if let arrayOfDictionaries = json as? [[String: AnyObject]] {
                for dictionary in arrayOfDictionaries {
                    clubs.append(Club(dictionary: dictionary))
                }
                completionHandler(clubs, nil)
            } else {
                completionHandler(nil, error)
            }
        }
    }
}

Очевидно, вам нужно изменить Club для обработки объекта словаря:

class Club {

    var id: String!
    var name: String!
    var imageUrl: String!
    var hasVippler: Bool!
    var location: [String: String]!

    init(dictionary: [String: AnyObject]) {
        id         = dictionary["_id"] as? String
        name       = dictionary["name"] as? String
        imageUrl   = dictionary["imageUrl"] as? String
        hasVippler = dictionary["hasVip"] as? Bool
        location   = dictionary["location"] as? [String: String]
    }
}

Наконец, ваш контроллер табличного представления может вызывать API:

let apiClient = ApiClient()

var clubs: [Club]!

override func viewDidLoad() {
    super.viewDidLoad()

    apiClient.getList() { clubs, error in
        if clubs != nil {
            self.clubs = clubs
            self.tableView.reloadData()
        } else {
            println(error)
        }
    }
}
person Rob    schedule 27.04.2015
comment
Извините, Роб, но вызов ApiClient.getList() { clubs, error in... вызывает эту ошибку. Не удается вызвать getList со списком аргументов типа ((,)-›_) - person Edu; 29.04.2015
comment
Извините, Роб, возвращаясь к этой теме, ответ json после request.responseJSON представляет собой массив [hits], но println(arrayOfDictionaries) пуст. Обратите внимание, что ответ JSON, который я напечатал сверху, представляет собой массив JSON после let data = jsonObj[hits].arrayValue as [JSON]?, потому что в этой строке я извлекаю [hits ] значение ответа JSON - person Edu; 05.05.2015
comment
Извините, Роб, я плохо объясняю, без использования swiftyjson ответ json представляет собой массив обращений, но когда я пытаюсь преобразовать его в [string: anyObject], тогда arrayOfDictionaries пуст. - person Edu; 05.05.2015
comment
да, Роб, ты прав, даже с [[String : AnyObject]] arrayOfDictionaries остается пустым после ответа json - person Edu; 05.05.2015
comment
Давайте продолжим обсуждение в чате. - person Edu; 05.05.2015