I am trying to decode the following bit of JSON from https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts|pageimages&exintro=&explaintext=&indexpageids&redirects=1&pithumbsize=500&titles=canterbury bells
{"batchcomplete":"","query":{"normalized":[{"from":"canterbury bells","to":"Canterbury bells"}],"redirects":[{"from":"Canterbury bells","to":"Campanula medium"}],"pageids":["5372595"],"pages":{"5372595":{"pageid":5372595,"ns":0,"title":"Campanula medium","extract":"Campanula medium, common name Canterbury bells, is an annual or biennial flowering plant of the genus Campanula, belonging to the family Campanulaceae. In floriography, it represents gratitude, or faith and constancy.","thumbnail":{"source":"https://upload.wikimedia.org/wikipedia/commons/thumb/8/86/Campanulaceae_-_Campanula_medium-4.JPG/500px-Campanulaceae_-_Campanula_medium-4.JPG","width":500,"height":375},"pageimage":"Campanulaceae_-_Campanula_medium-4.JPG"}}}}
I am using the following code, and I am trying to get the source URL of the thumbnail, among other things.
My datamodel:
struct FlowerData: Decodable {
let query: Query
}
struct Query: Decodable {
let pageids: [String]
let pages: [String: Pages]
let normalized: [[String: String]]
}
struct Pages: Decodable {
let extract: String
let thumbnail: [String: String]
}
My parsing code:
func parseJSON(_ flowerData: Data) -> FlowerModel? {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(FlowerData.self, from: flowerData)
let pageID = decodedData.query.pageids[0]
let name = decodedData.query.normalized[0]["from"]
let description = decodedData.query.pages[pageID]?.extract
let thumbnail = decodedData.query.pages[pageID]?.thumbnail["source"]
let flower = FlowerModel(flowerName: name!, description: description!, thumbnail: thumbnail!)
return flower
} catch {
delegate?.didFailWithError(error: error)
return nil
}
}
However, when I run this code, I am met with the following error:
typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "query", intValue: nil), CodingKeys(stringValue: "pages", intValue: nil), _JSONKey(stringValue: "5372595", intValue: nil), CodingKeys(stringValue: "thumbnail", intValue: nil), _JSONKey(stringValue: "width", intValue: nil)], debugDescription: "Expected to decode String but found a number instead.", underlyingError: nil))
The only one that fails is getting the URL of the thumbnail image. The name and description works as planned. What am I doing wrong? Any help will be greatly appreciated.
CodePudding user response:
The error is pretty clear. You need to decode a structure but you are defining thumbnail as a dictionary:
So you just need to change
struct Pages: Decodable {
let extract: String
let thumbnail: [String: String]
}
to
struct Pages: Decodable {
let extract: String
let thumbnail: Thumbnail
}
And define your Thumbnail structure as:
struct Thumbnail: Decodable {
let source: String
let width, height: Int
}
Then in your method you will also need to change
let thumbnail = decodedData.query.pages[pageID]?.thumbnail["source"]
to
let thumbnail = decodedData.query.pages[pageID]?.thumbnail.source