How to exclude properties from Swift Codable? How to exclude properties from Swift Codable? swift swift

How to exclude properties from Swift Codable?


The list of keys to encode/decode is controlled by a type called CodingKeys (note the s at the end). The compiler can synthesize this for you but can always override that.

Let's say you want to exclude the property nickname from both encoding and decoding:

struct Person: Codable {    var firstName: String    var lastName: String    var nickname: String?        private enum CodingKeys: String, CodingKey {        case firstName, lastName    }}

If you want it to be asymmetric (i.e. encode but not decode or vice versa), you have to provide your own implementations of encode(with encoder: ) and init(from decoder: ):

struct Person: Codable {    var firstName: String    var lastName: String        // Since fullName is a computed property, it's excluded by default    var fullName: String {        return firstName + " " + lastName    }    private enum CodingKeys: String, CodingKey {        case firstName, lastName, fullName    }    // We don't want to decode `fullName` from the JSON    init(from decoder: Decoder) throws {        let container = try decoder.container(keyedBy: CodingKeys.self)        firstName = try container.decode(String.self, forKey: .firstName)        lastName = try container.decode(String.self, forKey: .lastName)    }    // But we want to store `fullName` in the JSON anyhow    func encode(to encoder: Encoder) throws {        var container = encoder.container(keyedBy: CodingKeys.self)        try container.encode(firstName, forKey: .firstName)        try container.encode(lastName, forKey: .lastName)        try container.encode(fullName, forKey: .fullName)    }}


Another way to exclude some properties from encoder, separate coding container can be used

struct Person: Codable {    let firstName: String    let lastName: String    let excludedFromEncoder: String    private enum CodingKeys: String, CodingKey {        case firstName        case lastName    }    private enum AdditionalCodingKeys: String, CodingKey {        case excludedFromEncoder    }    init(from decoder: Decoder) throws {        let container = try decoder.container(keyedBy: CodingKeys.self)        let anotherContainer = try decoder.container(keyedBy: AdditionalCodingKeys.self)        firstName = try container.decode(String.self, forKey: .firstName)        lastName = try container.decode(String.self, forKey: .lastName)        excludedFromEncoder = try anotherContainer(String.self, forKey: . excludedFromEncoder)    }    // it is not necessary to implement custom encoding    // func encode(to encoder: Encoder) throws    // let person = Person(firstName: "fname", lastName: "lname", excludedFromEncoder: "only for decoding")    // let jsonData = try JSONEncoder().encode(person)    // let jsonString = String(data: jsonData, encoding: .utf8)    // jsonString --> {"firstName": "fname", "lastName": "lname"}}

same approach can be used for decoder


If we need to exclude decoding of a couple of properties from a large set of properties in the structure, declare them as optional properties. Code to unwrapping optionals is less than writing a lot of keys under CodingKey enum.

I would recommend using extensions to add computed instance properties and computed type properties. It separates codable comforming properties from other logic hence provides better readability.