0

I am trying to parse the following JSON into a class, but don't know how to approach this particular case.

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

I am trying to get the title and extract, but in order to do so, it requires that I go through the unique pageid. How would I do this using the Codable protocol?

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

1 Answer 1

0

My suggestion is to write a custom initializer:

Decode pages as [String:Page] dictionary and map the inner dictionaries according to the values in 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)
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.