Home > Software engineering >  SWIFT - JSON "Expected to decode Double but found a string/data instead."
SWIFT - JSON "Expected to decode Double but found a string/data instead."

Time:02-18

i have problem with my json response

When I use this func , I print all data corect

      URLSession.shared.dataTask(with: request) { data, response, error in
        if let data = data {
            if let jsonString = String(data: data, encoding: .utf8) {
                print(jsonString)
            }
        }
    } .resume()

i get this correct data:

"brand":"Lamborghini", "model":"Huracan", "color":"#0052ff" ,"registration":"K1TEST", "lat":50.244495, "lng":18.996143,

but when i am using JasonDecoder and Model struct

        URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data else {
            return
        }
        do {
            let decoder = JSONDecoder()
            let carData = try decoder.decode([Model].self, from: data)
            print(carData)
        } catch {
            print(error)
        }
    } .resume()

Model:

struct Model : Codable {
let brand : String
let model : String
let color : String
let registration : String
let lat : Double
let lng : Double }

CodingKeys(stringValue: "lat", intValue: nil)], debugDescription: "Expected to decode Double but found a string/data instead."

I know that this is something wrong whit lat and lng data but i don't know how to fix it. Help

CodePudding user response:

let lat : String

try this. from the error itself we can understand that you are getting lat as string and you are trying to parse as to double. I think the same thing will happen for lng also, so try to parse accordingly

CodePudding user response:

The problem you have identified, where lat and lng can be Double and sometimes String, can be dealt with the following code, to decode lat and lng into a consistent Double.

struct Model : Identifiable, Codable, Hashable {
    let id: String  // <-- an id is very usefull in SwiftUI code
    let brand : String
    let model : String
    let color : String
    let registration : String
    let lat : Double
    let lng : Double
    
    enum CodingKeys: String, CodingKey {
        case brand,model,color,registration,lat,lng
        case id = "_id"
    }
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        id = try values.decode(String.self, forKey: .id)
        brand = try values.decode(String.self, forKey: .brand)
        model = try values.decode(String.self, forKey: .model)
        color = try values.decode(String.self, forKey: .color)
        registration = try values.decode(String.self, forKey: .registration)
        
        // decode lat, when it comes as a String
        if let theString = try? values.decode(String.self, forKey: .lat),
            let latitude = Double(theString) {
            lat = latitude
        } else {
            lat = try values.decode(Double.self, forKey: .lat)
        }
        
        // decode lng, when it comes as a String
        if let theString = try? values.decode(String.self, forKey: .lng),
            let longitude = Double(theString) {
            lng = longitude
        } else {
            lng = try values.decode(Double.self, forKey: .lng)
        }
        
    }
}
  
  • Related