2

Let assume I have the class Opportunity, with an optional code field

class Opportunity: Codable {

    let id: String
    let code: String?

    enum OpportunityKeys: String, CodingKey {

        case id = "opportunityId"
        case code = "opportunityCode"
    }

    required init(from decoder: Decoder) throws {

        let values = try decoder.container(keyedBy: OpportunityKeys.self)

        id = try values.decode(String.self, forKey: .id)
        if let code = try? values.decode(String.self, forKey: .code) {
            self.code = code
        }
    }
}

Is there a way to parse a nil value better than using if let?

raed
  • 4,887
  • 4
  • 30
  • 49
  • Possible duplicate of [What is difference between optional and decodeIfPresent when using Decodable for JSON Parsing?](https://stackoverflow.com/questions/46292325/what-is-difference-between-optional-and-decodeifpresent-when-using-decodable-for) – Larme Jun 17 '18 at 12:45
  • @Larme, thanks for pointing this, but what I m asking is is there a better way to parse nil value other than if let. The other question is asking the difference between decode and decodeIfPresent. I believe they're different! What do you think? – raed Jun 17 '18 at 13:06
  • If it can be nil, then use `decodeIfPresent()` as said in the linked question and by @vadian. – Larme Jun 17 '18 at 13:14
  • For future reference, `decodeIfPresent` is the default method called for optional properties in a synthesized `init(from:)`. This means that if you let the compiler synthesize this (rename `OpportunityKeys` to `CodingKeys` and delete your `init(from:)` implementation), you’d get the same behavior out of the box. – Itai Ferber Jun 17 '18 at 14:41

2 Answers2

1

Yes, there is a better way

code = try values.decodeIfPresent(String.self, forKey: .code)

Avoid try? as much as possible.

vadian
  • 274,689
  • 30
  • 353
  • 361
  • I'd like to see a reason for this statement. – gnasher729 Jun 17 '18 at 15:55
  • @gnasher729 Especially `Codable` relies heavily on error handling. Almost every API `throws`. To write reliable code it's much better to handle the error rather than ignoring it. – vadian Jun 17 '18 at 18:52
0

Yeah, there is.

Since code is optional Just replace

if let code = try? values.decode(String.self, forKey: .code) {
    self.code = code
}

By

code = try? values.decode(String.self, forKey: .code)
raed
  • 4,887
  • 4
  • 30
  • 49
  • using try?, you are going to set code to nil on both cases: 1-decoding failure( due to type mismatch ) and 2-decoding failure( due to missing key). You may need to use decodeIfPresent as cited to have a change to handle type-mismatch – Idali Jun 19 '18 at 16:02