如何使用 Codable 解析具有动态文件名的 Swift 中的 JSON

How to parse JSON in Swift with dynamic filename using Codable

我正在尝试将以下 JSON 解析为 class,但不知道如何处理这种特殊情况。

这是api:https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=&explaintext=&indexpageids&titles=bird

我正在尝试获取标题和摘录,但为此,我需要通过唯一的 pageid。我将如何使用 Codable 协议执行此操作?

{ 
    "batchcomplete": "", 
    "query": { 
        "normalized": [
           {
               "from": "bird",
               "to": "Bird"
           }
         ],
         "pageids": [
             "3410"
         ],
         "pages": {
            "3410": {
                "pageid": 3410,
                "ns": 0,
                "title": "Bird",
                "extract": "..."
            }
         }
     }
}

我的建议是编写自定义初始化程序:

pages解码为[String:Page]字典并根据pageids

中的值映射内部字典
let jsonString = """
{
    "batchcomplete": "",
    "query": {
        "normalized": [
           {
               "from": "bird",
               "to": "Bird"
           }
         ],
         "pageids": [
             "3410"
         ],
         "pages": {
            "3410": {
                "pageid": 3410,
                "ns": 0,
                "title": "Bird",
                "extract": "..."
            }
         }
     }
}
"""

struct Root : Decodable {
    let query : Query
}

struct Query : Decodable {
    let pageids : [String]
    let pages : [Page]

    private enum CodingKeys : String, CodingKey { case pageids, pages }

    init(from decoder : Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.pageids = try container.decode([String].self, forKey: .pageids)
        let pagesData = try container.decode([String:Page].self, forKey: .pages)
        self.pages = self.pageids.compactMap{ pagesData[[=10=]] }
    }
}

struct Page : Decodable {
    let pageid, ns : Int
    let title, extract : String
}


let data = Data(jsonString.utf8)

do {
    let result = try JSONDecoder().decode(Root.self, from: data)
    print(result)
} catch {
    print(error)
}