Expected to decode Int but found a number instead

Jatin Chauhan picture Jatin Chauhan · Oct 27, 2018 · Viewed 8.8k times · Source

I had issue with JSON parsing in Swift 4.2. Here is the following code which shown runtime error.

My Json data is as follow which i got from server.

{
    code: 406,
    message: "Email Address already Exist.",
    status: 0
}

I am using Codable to create my structure as follow

struct Registration: Codable {
    var code: Int
    var status: Int
    private enum CodinggKeys: String, CodingKey {
        case code
        case status
    }
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        do {
            self.code = Int(try container.decode(String.self, forKey: .code))!
        } catch DecodingError.typeMismatch {
            let value = try container.decode(Double.self, forKey: .code)
            self.code = Int(value);
        }

        do {
            self.status = try container.decode(Int.self, forKey: .status)
        } catch DecodingError.typeMismatch {
            let value = try container.decode(String.self, forKey: .status)
            self.status = Int(value);
        }
    }
} 

But every time i got error on parsing status key.

Note: I had tried to parse status in String, Int, Double, Decimal, NSInterger but neither any works. every time i got the same error. Expected to decode UInt but found a number instead.

Answer

Gereon picture Gereon · Oct 27, 2018

The error message is very misleading. This happens when the JSON contains a boolean value, and the struct has an Int property for the corresponding key.

Most likely your JSON actually looks like this:

{
    "code": 406,
    "message": "Email Address already Exist.",
    "status": false
}

and accordingly, your struct should be

struct Registration: Codable {
    let code: Int
    let status: Bool
}

if let registration = try? JSONDecoder().decode(Registration.self, from: data) {
    print(registration.code) // 406
    print(registration.status) // false
}