1

Say I have a struct User model which has many properties in it.

struct User: Codable {
    let firstName: String
    let lastName: String
    // many more properties...
}

As you can see above it conforms to Codable. Imagine if the lastName property is should be encoded/decoded as secondName and I would like to keep it as lastName at my end, I need to add the CodingKeys to the User model.

struct User: Codable {
    //...
    private enum CodingKeys: String, CodingKey {
        case firstName
        case lastName = "secondName"
        // all the other cases...
    }
}

Is there any possible way to avoid including all the cases in CodingKeys that have the same value as rawValue like the firstName in the above example (Feels redundant)? I know if I avoid the cases in CodingKeys it won't be included while decoding/encoding. But, is there a way I could override this behaviour?

Frankenstein
  • 15,732
  • 4
  • 22
  • 47
  • Let me know If I'm not clear enough or if this is a duplicate I could only find the one's that said how to exclude unnecessary(not required while encoding/decoding) keys. – Frankenstein Jul 03 '20 at 09:31
  • 1
    you are not participating from last 2 days :p is everything good ? – Jawad Ali Jul 03 '20 at 09:46

2 Answers2

2

There is a codable way, but the benefit is questionable.

Create a generic CodingKey

struct AnyKey: CodingKey {
    var stringValue: String
    var intValue: Int?

    init?(stringValue: String) { self.stringValue = stringValue; self.intValue = nil }
    init?(intValue: Int) { self.stringValue = String(intValue); self.intValue = intValue }
}

and add a custom keyDecodingStrategy

struct User: Codable {
    let firstName: String
    let lastName: String
    let age : Int
}

let jsonString = """
{"firstName":"John", "secondName":"Doe", "age": 30}
"""

let data = Data(jsonString.utf8)

do {
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .custom({ keyPath -> CodingKey in
        let key = keyPath.last!
        return key.stringValue == "secondName" ? AnyKey(stringValue:"lastName")! : key
    })
    let result = try decoder.decode(User.self, from: data)
    print(result)
} catch {
    print(error)
}
vadian
  • 274,689
  • 30
  • 353
  • 361
1

There is not such a feature at this time. But you can take advantage of using computed properties and make the original one private.

struct User: Codable {
    var firstName: String
    private var secondName: String
    var lastName: String { 
        get { secondName }
        set { secondName = newValue }
    }
}

So no need to manual implementing of CodingKeys at all and it acts exactly like the way you like. Take a look at their counterparts:

Preview1

Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278