首页 > 解决方案 > 使用 Swift 访问 JSON 中的嵌套字典

问题描述

我想解析以下JSON,以便从 Wikipedia 的 API 中获取随机文章的 ID 并在 Swift 中使用它:

{
"batchcomplete": "",
"continue": {
    "rncontinue": "0.067678657404|0.067678667039|13394072|0",
    "continue": "-||"
},
"query": {
    "random": [
        {
            "id": 34538560,
            "ns": 3,
            "title": "User talk:59.188.42.121"
        }
    ]
}
}

我希望能够从中访问"id""title"值,我目前可以访问以下内容"query"

let url = URL(string: "https://en.wikipedia.org/w/api.php?action=query&list=random&rnlimit=1&format=json")
    URLSession.shared.dataTask(with: url!) { (data, response, err) in
        guard let data = data else { return }
        if err != nil {
            print(err!)
        } else {
            do {
                let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? NSDictionary
                if let result = json! as? [String: AnyObject] {
                    if let result = result["query"]! as? [String: AnyObject] {
                        print(result)
                    }
                }
            } catch {
                print("Error")
            }
        }
    }.resume()

现在,按我的方式进行类型转换并不是我引以为豪的事情,而且它很快就会变得非常混乱。我还通过执行以下操作尝试过一次类型转换,但无济于事:

[String: [String: [String:AnyObject]]]

有没有更好的方法来访问这些值?任何帮助将不胜感激!

标签: jsonswift

解决方案


如果您使用的是 Swift 4,则有Codable. 使用Codable涉及为 JSON 定义自定义结构/类,但诸如quicktype.io之类的应用程序可以让这变得轻而易举:您只需粘贴 JSON,它就会为您生成结构。

首先,保存来自维基百科的响应的结构:

struct Response: Codable {
    struct Query: Codable {
        let random: [Random]
    }

    struct Random: Codable {
        let id, ns: Int
        let title: String
    }

    struct Continue: Codable {
        let rncontinue, continueContinue: String

        enum CodingKeys: String, CodingKey {
            case rncontinue
            case continueContinue = "continue"
        }
    }

    let batchcomplete: String
    let `continue`: Continue
    let query: Query

    enum CodingKeys: String, CodingKey {
        case batchcomplete, `continue`, query
    }
}

并解码 JSON:

let url = URL(string: "https://en.wikipedia.org/w/api.php?action=query&list=random&rnlimit=1&format=json")
URLSession.shared.dataTask(with: url!) { (data, response, err) in
    guard let data = data else { return }
    guard err == nil else { print(err!); return }

    do {
        let response = try JSONDecoder().decode(Response.self, from: data)
        if let firstArticle = response.query.random.first {
            print(firstArticle)
        } else {
            print("No Article")
        }
    } catch {
        print(error)
    }
}.resume()

推荐阅读