SwiftyJSON 代码 - why/how 这行得通吗?
SwiftyJSON code - why/how does this work?
我一直在自学如何使用 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" 和 "type" 中获取 "name" 值的数组。我从这里尝试了很多不同的建议,关于他们 Github 的 SwiftyJSON 指南和其他各种来源,我唯一可以开始工作的是:
let typesArray = json["types"].arrayValue.map({[=12=]["type"]["name"].stringValue})
for item in typesArray {
self.currentPokemon.pokemonTypes.append(item.firstUppercased)
print("Added \(item)")
}
我很高兴它能正常工作,但我拼命想着手解析 JSON,但这对我来说毫无意义!任何人都可以向我解释发生了什么事吗?有更清晰/更易读的方法吗?
感谢您的宝贵时间!
JSON
首先要做的事情...我认为您需要确保自己真正理解 JSON,然后才能全神贯注于此处所做的事情。 JSON 对象本质上是一个键/值对象。键是一个字符串,值可以是很多东西:更多 JSON 对象的数组,甚至像字符串一样简单。
最佳实践
所以当我必须通过 JSON 解析任何响应时,我喜欢做的一件事是创建一个字符串枚举,它将包含 json 中的所有 "Keys" .请注意,如果您没有为任何情况分配一个值并且类型为 String
当您执行 pokemonApiParams.name.rawValue
它将自动 return stringified 版本你的情况!
enum pokemonApiParams: String {
case baseExperience
case types
case slot
case type
case url
case name
}
现在,当您使用 JSON 时,您可以使用此枚举来帮助使事情变得更清楚。如果您的 API 响应曾经更改过密钥,这尤其好。您可以只更改枚举值,一切都会起作用!这是 "best practice" 的另一个原因是它从您的代码中删除了这些 "magic strings" 并将所有内容保存在一个后勤位置,您以后可以参考!
// This would give you 155 in your example
json[pokemonApiParams.baseExperience.rawValue]
完成您的示例
现在是您难以理解的部分。
首先让我们逐步重建您的 "types array"...
let typesArray = json[pokemonApiParams.types.rawValue]
这家伙创建了一个 json 对象,其中包含您响应中的 "types" 数组。基本的 SwiftyJSON 对象很棒,但您可以在此处更具体一点以获得更多用法,因此您的示例使用 .arrayValue
.
的原因
let typesArray = json[pokemonApiParams.types.rawValue].arrayValue
现在我们有一个 JSON 数组对象,我们可以使用各种不同的循环函数遍历它。但是接下来您将使用 .map
函数。习惯了再用,这家伙超级好用!
了解 .map
基本上我们可以将数组中的每个元素映射为其他元素,在这种情况下,我们使用简写来遍历数组并仅获取每种类型的 "name" 属性。所以我们从 [JSON] -> String
.
映射
$0 就是我说的 shorthand。将其想象为 for 循环中的索引。 map 函数将遍历整个数组,$0 是数组中正在查看的对象。
也请查看 map 文档!
综合起来
查看您的回复,每个 types 对象都有一个 slot 和一个 type。
所以回到你的例子(但使用我们的枚举!):
let typesArray = json[pokemonApiParams.types.rawValue].arrayValue
.map {
[=14=][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 shorthand 并且我们指定我们是什么 returning(字符串)。
希望这一切都是正确和清楚的!
祝你编码愉快,赶快赶上他们吧!
我一直在自学如何使用 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" 和 "type" 中获取 "name" 值的数组。我从这里尝试了很多不同的建议,关于他们 Github 的 SwiftyJSON 指南和其他各种来源,我唯一可以开始工作的是:
let typesArray = json["types"].arrayValue.map({[=12=]["type"]["name"].stringValue})
for item in typesArray {
self.currentPokemon.pokemonTypes.append(item.firstUppercased)
print("Added \(item)")
}
我很高兴它能正常工作,但我拼命想着手解析 JSON,但这对我来说毫无意义!任何人都可以向我解释发生了什么事吗?有更清晰/更易读的方法吗?
感谢您的宝贵时间!
JSON
首先要做的事情...我认为您需要确保自己真正理解 JSON,然后才能全神贯注于此处所做的事情。 JSON 对象本质上是一个键/值对象。键是一个字符串,值可以是很多东西:更多 JSON 对象的数组,甚至像字符串一样简单。
最佳实践
所以当我必须通过 JSON 解析任何响应时,我喜欢做的一件事是创建一个字符串枚举,它将包含 json 中的所有 "Keys" .请注意,如果您没有为任何情况分配一个值并且类型为 String
当您执行 pokemonApiParams.name.rawValue
它将自动 return stringified 版本你的情况!
enum pokemonApiParams: String {
case baseExperience
case types
case slot
case type
case url
case name
}
现在,当您使用 JSON 时,您可以使用此枚举来帮助使事情变得更清楚。如果您的 API 响应曾经更改过密钥,这尤其好。您可以只更改枚举值,一切都会起作用!这是 "best practice" 的另一个原因是它从您的代码中删除了这些 "magic strings" 并将所有内容保存在一个后勤位置,您以后可以参考!
// This would give you 155 in your example
json[pokemonApiParams.baseExperience.rawValue]
完成您的示例
现在是您难以理解的部分。
首先让我们逐步重建您的 "types array"...
let typesArray = json[pokemonApiParams.types.rawValue]
这家伙创建了一个 json 对象,其中包含您响应中的 "types" 数组。基本的 SwiftyJSON 对象很棒,但您可以在此处更具体一点以获得更多用法,因此您的示例使用 .arrayValue
.
let typesArray = json[pokemonApiParams.types.rawValue].arrayValue
现在我们有一个 JSON 数组对象,我们可以使用各种不同的循环函数遍历它。但是接下来您将使用 .map
函数。习惯了再用,这家伙超级好用!
了解 .map
基本上我们可以将数组中的每个元素映射为其他元素,在这种情况下,我们使用简写来遍历数组并仅获取每种类型的 "name" 属性。所以我们从 [JSON] -> String
.
$0 就是我说的 shorthand。将其想象为 for 循环中的索引。 map 函数将遍历整个数组,$0 是数组中正在查看的对象。
也请查看 map 文档!
综合起来
查看您的回复,每个 types 对象都有一个 slot 和一个 type。
所以回到你的例子(但使用我们的枚举!):
let typesArray = json[pokemonApiParams.types.rawValue].arrayValue
.map {
[=14=][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 shorthand 并且我们指定我们是什么 returning(字符串)。
希望这一切都是正确和清楚的!
祝你编码愉快,赶快赶上他们吧!