Как разобрать JSON в Swift с динамическим c именем файла, используя Codable - PullRequest
0 голосов
/ 15 апреля 2020

Я пытаюсь разобрать следующие JSON в классе, но не знаю, как подходить к этому конкретному случаю.

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

Я пытаюсь получить заголовок и извлечь, но для этого требуется, чтобы я go через уникальный Pageid. Как бы я сделал это, используя протокол Codable?

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

1 Ответ

0 голосов
/ 15 апреля 2020

Я предлагаю написать пользовательский инициализатор:

Декодировать 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[$0] }
    }
}

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)
}
...