Как я могу разобрать этот словарь покемонов JSON?API покемонов (swift 3) - PullRequest
0 голосов
/ 25 ноября 2018

У меня проблема с анализом данных JSON из новой версии API Pokemon, в частности со значениями ключа "name" in "type".

Json выглядит следующим образом:

"types": [
    {
        "slot": 2,
        "type": {
            "name": "poison",
            "url": "https://pokeapi.co/api/v2/type/4/"
        }
    },
    {
        "slot": 1,
        "type": {
            "name": "grass",
            "url": "https://pokeapi.co/api/v2/type/12/"
        }
    }
],
"weight": 69

После разбора в Alamofire я получил следующее решение:

if let types = dict["types"] as? [Dictionary<String, String>] , types.count > 0 {

                if let type = types[0]["type"] as? Dictionary<String, String> {

                    if let name = type["name"] {
                        self._type = name.capitalized
                    }
                }

                print("TypeAA: \(self._type)")

            } else {

                self._type = ""
            }

И эта строка также не будет выполнена.print ("TypeAA: (self._type)") Посоветуйте, пожалуйста, как я могу правильно проанализировать и получить значение "name" в ключе named "type"?

Ответы [ 4 ]

0 голосов
/ 25 ноября 2018

Ваш код не работает из-за сбоя первого условного понижения.

Значение ключа types равно [Dictionary<String, Any>] (обратите внимание на вложенный словарь в JSON), а не [Dictionary<String, String>].

Так что в основном это работает

 if let types = dict["types"] as? [Dictionary<String, Any>] , types.count > 0 {
    if let type = types[0]["type"] as? Dictionary<String, String> {
       if let name = type["name"] {
          self._type = name.capitalized
       }
    }
    print("TypeAA: \(self._type)")
 } else {
    self._type = ""
 }

Но пирамида гибели громоздка и никогда не проверяет пустой массив с .count > 0, так что этоболее эффективный

 if let types = dict["types"] as? [Dictionary<String, Any>], 
    let firstType = types.first, let typeInfo = firstType["type"] as? Dictionary<String, String>,
    let name = typeInfo["name"] {
       self._type = name.capitalized
       print("TypeAA:", self._type)
 } else {
    self._type = ""
 }

Если вам нужно рассмотреть все имена, вы должны использовать цикл

 if let types = dict["types"] as? [Dictionary<String, Any>] {
    for type in types {
        if let typeInfo = type["type"] as? Dictionary<String, String>,
           let name = typeInfo["name"] {
           print("TypeAA:", name)
        }
   }
 } else {
    self._type = ""
 }

Если вы хотите напечатать все имена через запятую, используйте

if let types = dict["types"] as? [Dictionary<String, Any>] {
    let names = types.compactMap { type -> String? in
        guard let typeInfo = type["type"] as? Dictionary<String, String>,
            let name = typeInfo["name"] else { return nil }
        return name
    }
    print(names.joined(separator: ", "))
}
0 голосов
/ 25 ноября 2018

Или попробуйте что-нибудь подобное здесь:

if let types = dict["types"] as? [Any] {
    guard types.count > 0 else {
        return
    }

    for elment in types {
        if let type = elment["type"] as? [String:Any] {
            let name = type["name"] as! String
            // Do what you want with it here
        }
    }
}
0 голосов
/ 25 ноября 2018

Вы можете использовать AlamofireObjectMapper для очень простого анализа ответа JSON от Alamofire.

class PokemonTypesResponse: Mappable {
    var types:[Types]?
    var weight:Int?

    required init?(map: Map){

    }

    func mapping(map: Map) {
        types <- map["types"]
        weight <- map["weight"]
    }
}

class Types: Mappable {
    var slot:Int?
    var name:String?
    var url:String?

    required init?(map: Map){

    }

    func mapping(map: Map) {
        slot <- map["slot"]
        type <- map["type.name"]
        url  <- mapp["type.url"]
    }
}

Выполнить запрос с помощью alamofire и использовать

.responseArray { (response: DataResponse<[PokemonTypesResponse]>) in
switch response.result {
            case .success:
                //this is the response as PokemonTypesResponse
                response.result.value 
            case .failure(let error):
                print(error)
            }

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

0 голосов
/ 25 ноября 2018

Вы не можете сделать dict["types"] as? [Dictionary<String, String>], потому что элемент в types не может быть приведен к Dictionary<String, String>.item имеет целые числа, такие как "slot": 2 и словари "type": {...}.Так что сначала нужно привести к [String : Any].

if let types = dict["types"] as? [Any], types.count > 0 {
    if let firstObject = (types.first as? [String : Any]),
        let type = firstObject["type"] as? [String : String],
        let name = type["name"] {
            self._type = name.capitalized
    }
}

если вам нужно имя каждого элемента, вы должны перебрать массив items.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...