Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get specific CodingKey for KeyPath

Consider the following object:

struct User: Codable {
    let id: Int
    let email: String
    let name: String
}

Is it posible to get a specific CodingKey for a given KeyPath?

let key = \User.name.codingKey  // would be equal to string: "name"
like image 985
Wiingaard Avatar asked Oct 01 '17 11:10

Wiingaard


People also ask

What is swift Codingkey?

A type that can be used as a key for encoding and decoding.

What is Codable protocol in Swift?

The Codable protocol in Swift is really a union of two protocols: Encodable and Decodable . These two protocols are used to indicate whether a certain struct, enum, or class, can be encoded into JSON data, or materialized from JSON data.


1 Answers

Using Swift 4, I don't think you can automatically retrieve a CodingKey from the corresponding KeyPath object but you can always hack your way around it ;)

For instance, in the same User type Swift source file, add the following extension:

fileprivate extension User {
    static func codingKey(for keyPath: PartialKeyPath<User>) -> CodingKey {
        switch keyPath {
        case \User.id:    return CodingKeys.id
        case \User.email: return CodingKeys.email
        case \User.name:  return CodingKeys.name
        default: fatalError("Unexpected User key path: \(keyPath)")
        }
    }
}

then implement the desired codingKey API in the constrained KeyPath superclass:

extension PartialKeyPath where Root == User {
    var codingKey: CodingKey {
        return User.codingKey(for: self)
    }
}

Finally, the usage follows closely your code:

let name: CodingKey = (\User.name).codingKey
print("\(name)") // prints "name"

This may be a somewhat tedious and error prone solution but, if you only need this capability for handful of types, it's perfectly doable in my opinion ;)

Caveats. This hack, of course, won't work for externally defined types given CodingKeys enum private visibility. (For instance, for all Codable types defined by the Swift Standard Library.)

like image 165
Paulo Mattos Avatar answered Nov 01 '22 05:11

Paulo Mattos