Abdullah
Abdullah

Reputation: 55

Why Decodable's init method isn't called when using JSONDecoder.decode method?

I'm trying to override how JSONDecoder decode a data.

I tried the following:

struct Response : Decodable {
    init(from decoder: Decoder) throws {
        print("Hello")
    }
}

let result = try JSONDecoder().decode(Response.self, from: Data())

But the init(from:) does not get called. Basically I want the JSONDecoder to always success when decoding empty data to empty Response object

Upvotes: 2

Views: 1856

Answers (2)

Tiago Mendes
Tiago Mendes

Reputation: 5146

Whoever comes to this page looking for a solution to force use of INIT on decodable class you just need to use:

required init(from decoder: Decoder) throws {

Full example:

class DeviceListElement: Codable {
    
    var firmwareVersion, deviceName: String
    var status: Int
    
    
    enum CodingKeys: String, CodingKey {
        case firmwareVersion = "fwVer"
        case deviceName
        case status
    }
    

    required init(from decoder: Decoder) throws {
        
        let container = try decoder.container(keyedBy: CodingKeys.self)
        firmwareVersion = try container.decode(String.self, forKey: .firmwareVersion)
        deviceName = try container.decode(String.self, forKey: .deviceName)
        status = try container.decode(Int.self, forKey: .status)
        
        
        //if is optional use this: container.decodeIfPresent(String.self, forKey: .blabla)
    }
    
}

Upvotes: -1

vadian
vadian

Reputation: 285079

An empty Data object causes the init method to throw the error

The given data was not valid JSON.

before "Hello" gets printed.


If you want to get an empty Response object (assuming you don't have to call any designated initializer) catch the dataCorrupted decoding error

struct Response : Decodable {}

var response : Response?
do {
    response = try JSONDecoder().decode(Response.self, from: Data())
} catch DecodingError.dataCorrupted(let context) where (context.underlyingError as NSError?)?.code == 3840 { // "The given data was not valid JSON."
    response = Response()
} catch { print(error) }

Upvotes: 4

Related Questions