SwiftyJSON代码 - 为什么/如何工作?

时间:2017-11-18 21:08:51

标签: json swift swifty-json

我一直在教自己如何使用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,这对我来说没有意义!有人可以向我解释发生了什么事吗?这样做有更清晰/更易读的方法吗?

感谢您的时间!

1 个答案:

答案 0 :(得分:0)

JSON

首先要做的事情......我认为你需要确保你真正了解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功能。一旦你习惯了它并且再使用它,这个人就非常有用了!

了解.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)。

希望这一切都正确而明确!

快乐编码并抓住所有人!