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.)
CodingKeys
are private to the type, so you won't be able to access them outside of that type. What are you looking to do here? – WardroomCodingKey
from aKeyPath
. Most recent use case was building a strongly-typed wrapper around the Firebase Database API, so instead of sayingsomeRef.child("foo").child("bar").observe(.value) { snapshot in /* snapshot.value is an Any? ew. */}
you would saysomeProvider.observeValue(at: \.foo.bar) { value in /* value is typed as whatever the type of bar is */ }
. To implement, had to have each type provide a dictionary that mapped immediate child key paths to coding keys (in a 1:1 manner)... – WealthyCodingKey
, soCodingKeys
didn't need to be exposed. Then had to iterate through the entire tree of properties from a given root type, building up a key path and comparing it with the argument; which wasn't ideal. It would certainly be nice if the language provided some way to automatically do that mapping for you; although that being said, I'm not sure it'd be viable for types that implement their own custom encoding/decoding logic. – Wealthy