如何解析这个 JSON 口袋妖怪字典?口袋妖怪 API (swift 3)
Posted
技术标签:
【中文标题】如何解析这个 JSON 口袋妖怪字典?口袋妖怪 API (swift 3)【英文标题】:How can I parse this JSON Pokemon Dictionary? Pokemon API (swift 3) 【发布时间】:2018-11-25 05:36:15 【问题描述】:我在解析来自新版 Pokemon API 的 JSON 数据时遇到问题,特别是“type”键中的“name”值。
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”的值?
【问题讨论】:
使用Decodable比手动解析响应要容易得多。 感谢@Kamran,但请就这些代码提出建议。 【参考方案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
数组。
【讨论】:
您的解决方案有效,但您的陈述是错误的。[Dictionary<String, String>]
也是一个字典数组。如果你检查first
,检查空是多余的。【参考方案2】:
或者在这里尝试类似的东西:
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
【讨论】:
【参考方案3】:您可以使用 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 结果 我没有测试过,我是根据我的经验写的。 我希望它有效并且易于理解。
【讨论】:
【参考方案4】:您的代码不起作用,因为第一个条件向下转换失败。
键 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: ", "))
【讨论】:
#Vadian,您的解决方案很容易理解并且有效。这对我很有帮助。非常感谢。 对不起,我还是一头雾水。 对不起,我还是一头雾水。我使用你的循环代码,但似乎只有一种类型被正确获取。控制台日志如下所示。 TypeAA:毒 TypeAA:bug 到这里了吗? 2018-11-25 18:27:20.067718+0700 PokeMum[11401:1131765] TIC 读取状态 [1:0x0]: 1:57 2018-11-25 18:27:20.067883+0700 PokeMum[11401:1131765] TIC 读取Status [1:0x0]: 1:57 而我的预期是打印出来:“Poison/Grass”(2 种),如何执行? 在给定的 JSON 中没有字符串bug
。而TypeAA: poison / TypeAA: bug
是 2 种类型。每种类型都单独打印。
谢谢@vadian,还有一个问题,在使用循环代码时,如何打印出这样的字符串:“Poison/Grass”。我是新手,请多多指教。以上是关于如何解析这个 JSON 口袋妖怪字典?口袋妖怪 API (swift 3)的主要内容,如果未能解决你的问题,请参考以下文章