0

What I have: A codable struct with different properties.

What I want: A function, where I can get the exact name of the property when it is encoded in a Json. I think the most promising approach is using Keypath, but I have no idea how and whether it is possible at all. Thanks!

NaveedUlHassan5
  • 235
  • 1
  • 14
Nicolas Degen
  • 1,522
  • 2
  • 15
  • 24
  • 2
    Coding keys do not necessarily correspond to properties. It just so happens that that is the case for most use cases. – Sweeper Oct 12 '20 at 09:17

1 Answers1

5

There is no way to do this out of the box, since there's no 1-1 mapping between properties of a Codable type and its coding keys, since there might be properties that aren't part of the encoded model or properties that depend on several encoded keys.

However, you should be able to achieve your goals by defining a mapping between the properties and their coding keys. You were on the right track with KeyPaths, you just need to define a function that takes a KeyPath whose root type is your codable model and return the coding key from said function.

struct MyCodable: Codable {
    let id: Int
    let name: String

    // This property isn't part of the JSON
    var description: String {
        "\(id) \(name)"
    }

    enum CodingKeys: String, CodingKey {
        case name = "Name"
        case id = "identifier"
    }

    static func codingKey<Value>(for keyPath: KeyPath<MyCodable, Value>) -> String? {
        let codingKey: CodingKeys
        switch keyPath {
        case \MyCodable.id:
            codingKey = .id
        case \MyCodable.name:
            codingKey = .name
        default: // handle properties that aren't encoded
            return nil
        }
        return codingKey.rawValue
    }
}

MyCodable.codingKey(for: \.id)
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
  • Nice. My goal though is a general / templated method that works for default coding keys. I guess it is not possible! – Nicolas Degen Oct 12 '20 at 12:30
  • It’s good, but take the “s” off of that type! And make it a subscript of that type instead of a method. e.g. `MyCodable.CodingKey[\.id]?.rawValue` Or an initializer. –  Oct 12 '20 at 12:43
  • @NicolasDegen sadly no, since you cannot access the default coding keys, because they're synthesised by the compiler and aren't publicly exposed – Dávid Pásztor Oct 12 '20 at 12:58