Home > Net >  "Expected to decode String but found a number instead." Issue decoding JSON
"Expected to decode String but found a number instead." Issue decoding JSON

Time:07-23

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
  • Related