我一直在教自己如何使用SwiftyJSON和fab PokeApi.co解析JSON我以为我已经掌握了它,直到我试图获得一个口袋妖怪的不同类型的数组。返回的JSON如下所示:
...
],
"base_experience": 155,
"types": [
{
"slot": 2,
"type": {
"url": "https://pokeapi.co/api/v2/type/3/",
"name": "flying"
}
},
{
"slot": 1,
"type": {
"url": "https://pokeapi.co/api/v2/type/1/",
"name": "normal"
}
}
]
}
我需要在“types”中获取“name”的值数组,然后“type”。我从这里尝试了很多不同的建议,关于他们的Github上的SwiftyJSON指南和其他各种来源,我唯一可以工作的是:
let typesArray = json["types"].arrayValue.map({$0["type"]["name"].stringValue})
for item in typesArray {
self.currentPokemon.pokemonTypes.append(item.firstUppercased)
print("Added \(item)")
}
我很高兴我能让它发挥作用,但我正在拼命试图解析JSON,这对我来说没有意义!有人可以向我解释发生了什么事吗?这样做有更清晰/更易读的方法吗?
感谢您的时间!
答案 0 :(得分:0)
首先要做的事情......我认为你需要确保你真正了解JSON,然后再能够了解你在这里所做的事情。 JSON对象本质上是一个Key / Value对象。 Key是一个字符串,值可以是很多东西:更多JSON对象的数组,甚至像字符串一样简单。
因此,当我必须通过JSON解析任何响应时,我喜欢做的一件事是创建一个包含所有" Keys"在json。请注意,如果您没有为任何案例分配一个calue,而String
类型为pokemonApiParams.name.rawValue
,则会自动返回您案例的字符串化版本!
enum pokemonApiParams: String {
case baseExperience
case types
case slot
case type
case url
case name
}
现在,当您使用JSON时,您可以使用此枚举来帮助您更清楚地了解情况。如果您的API响应曾经更改过密钥,那么这一点尤为出色。你可以只改变枚举值,一切都会奏效!这是最佳实践的另一个原因"它取出了这些"魔术字符串"从您的代码中将所有内容保存在一个后勤位置,以后可以参考!
// This would give you 155 in your example
json[pokemonApiParams.baseExperience.rawValue]
现在到了你无法理解的部分。
首先让我们重建你的"类型数组"一块一块......
let typesArray = json[pokemonApiParams.types.rawValue]
这个人创建了一个json对象,其中包含"类型"在你的回复中。基本的SwiftyJSON对象很棒但是你可以在这里更具体一些,以获得更多的用法,因此你的例子使用.arrayValue
。
let typesArray = json[pokemonApiParams.types.rawValue].arrayValue
现在我们有一个JSON数组对象,我们可以使用各种不同的循环函数来完成它。但是,接下来使用.map
功能。一旦你习惯了它并且再使用它,这个人就非常有用了!
基本上我们可以将数组中的每个元素映射为其他元素,在这种情况下,我们使用简短的手来遍历数组并仅获取" name"每种类型的属性。所以我们从[JSON] -> String
。
$ 0是我正在谈论的简写。想象一下这是for循环中的索引。 map函数将遍历整个数组,$ 0是正在查看的数组中的对象。
查看map文档!
查看您的回复,每个类型对象都有插槽和类型。
回到你的例子(但使用我们的枚举!):
let typesArray = json[pokemonApiParams.types.rawValue].arrayValue
.map {
$0[pokemonApiParams.type][pokemonApiParams.name.rawValue].stringValue
}
现在您的typesArray是一个字符串数组。写这个的另一种方式(这将更清晰,也许更容易理解)是:
let typesArray = json[pokemonApiParams.types.rawValue].arrayValue
.map { (types: JSON) -> String in
types[pokemonApiParams.type.rawValue][pokemonApiParams.name.rawValue].stringValue
}
这更清楚,因为我们必须指定我们的对象(类型)而不是使用$ 0简写,我们指定我们返回的内容(String)。
希望这一切都正确而明确!
快乐编码并抓住所有人!