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 一起使用?

使用 Cocoapods 导入 SwiftyJSON 时出错

SwiftyJSON:如何添加令牌?