如何解析此JSON Pokemon词典?宠物小精灵API(Swift 3)

时间:2018-11-25 05:36:15

标签: ios json swift parsing

我在解析新版Pokemon API中的JSON数据时遇到问题,特别是在“类型”键中使用“名称”的值。

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)”) 请告知,如何正确解析并获取名为“ type”的键中“ name”的值?

4 个答案:

答案 0 :(得分:1)

您无法执行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数组。

答案 1 :(得分:0)

或在此处尝试类似的操作:

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

答案 2 :(得分:0)

您可以使用AlamofireObjectMapper轻松解析来自Alamofire的JSON响应。

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结果 我还没有测试过,而是根据经验编写的。 我希望它能正常工作并且易于理解。

答案 3 :(得分:0)

您的代码不起作用,因为第一个条件下调失败。

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: ", "))
}