Codable Struct: Get Value by Key

1.4k Views Asked by At

I have for example codable struct User:

struct User: Codable {
    // ...
    var psnTag: String?
    var xblTag: String?
    var steamTag: String?
    var nintendoTag: String?
    var instagramId: String?
    // ...
}

and stringKey as String = "psnTag"

How can I get the value from instance by stringKey?

Like this:

let stringKey = "psnTag"
user.hasKeyForPath(stringKey) //return Bool
user.valueForPath(stringKey) //return AnyObject
1

There are 1 best solutions below

4
Robert Dresler On

Start with extending Encodable protocol and declare methods for hasKey and for value

Using Mirror

extension Encodable {
    func hasKey(for path: String) -> Bool {
        return Mirror(reflecting: self).children.contains { $0.label == path }
    }
    func value(for path: String) -> Any? {
        return Mirror(reflecting: self).children.first { $0.label == path }?.value
    }
}

Using JSON Serialization

extension Encodable {
    func hasKey(for path: String) -> Bool {
        return dictionary?[path] != nil
    }
    func value(for path: String) -> Any? {
        return dictionary?[path]
    }    
    var dictionary: [String: Any]? {
        return (try? JSONSerialization.jsonObject(with: JSONEncoder().encode(self))) as? [String: Any]
    }
}

Now you can use it like this:

.hasKey(for: "key") //returns Bool
.value(for: "key") //returns Any?