SwiftyJSON 代码 - 为啥/如何工作?
Posted
技术标签:
【中文标题】SwiftyJSON 代码 - 为啥/如何工作?【英文标题】:SwiftyJSON code - why/how does this work?SwiftyJSON 代码 - 为什么/如何工作? 【发布时间】:2017-11-18 21:08:50 【问题描述】:我一直在自学如何使用 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,这对我来说没有意义!有人可以向我解释发生了什么吗?有没有更清晰/更易读的方法?
感谢您的宝贵时间!
【问题讨论】:
该代码的哪一点你不明白?你写的,你一定懂的。 对不起 - 我得到了除该行之外的所有内容:let typesArray = json["types"].arrayValue.map($0["type"]["name"].stringValue)跨度> 是的,这很重要。那条线具体是什么?你写的,你必须至少理解那行的一部分。 所以我知道我正在创建一个关键“类型”的数组。第二部分是否向下钻取以获取“名称”键的值? $0 是怎么回事? 在 Swift 书中了解 Closures。 【参考方案1】:JSON
首先要做的事情...我认为您需要确保您真正了解 JSON,然后才能了解您在这里所做的事情。 JSON 对象本质上是一个键/值对象。 Key 是一个字符串,而 value 可以是很多东西:更多 JSON 对象的数组,甚至像字符串一样简单。
最佳实践
所以当我必须通过 JSON 解析任何响应时,我喜欢做的一件事是创建一个字符串枚举,该枚举将在 json 中包含所有“键”。请注意,如果您没有为任何案例分配计算并且类型为 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
函数。这家伙一旦你习惯了它并使用它就会非常有用!
了解.map
基本上,我们可以将数组中的每个元素映射为其他元素,在这种情况下,我们使用简写方式遍历数组并仅获取每种类型的“名称”属性。所以我们从[JSON] -> String
映射。
$0 是我所说的简写。将其想象为 for 循环中的索引。 map 函数将遍历整个数组,$0 是正在查看的数组中的对象。
也请查看map 文档!
把它们放在一起
查看您的响应,每个 types 对象都有一个 slot 和一个 type。
回到你的例子(但使用我们的枚举!):
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 简写,并且我们指定我们返回的内容(字符串)。
希望这一切都是正确和清晰的!
祝你编码愉快,去抓他们!
【讨论】:
哇!非常感谢您使这一点更加清晰。我一定会阅读 .map 函数以及闭包。超级有用的解释-希望将来也能帮助像我这样的菜鸟!再次感谢!以上是关于SwiftyJSON 代码 - 为啥/如何工作?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 SwiftyJSON 无法在 swift 3 中解析数组字符串
如何将 RxSwift 与 AlamoFire 和 SwiftyJSON 一起使用?
SwiftyJSON 不工作 / Swift 1.2 SwiftyJSON 文件
如何将 DispatchSemaphore 与 Alamofire 和 SwiftyJSON 一起使用?