Created
December 14, 2022 15:37
-
-
Save DanielCardonaRojas/c3bda98a172dde07918c25bc917cd7ea to your computer and use it in GitHub Desktop.
Reach deeply nested object without having to create all intermediate CodingKeys
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Nested<T: Decodable>: Decodable | |
{ | |
let value: T | |
enum DecodeError: Error | |
{ | |
case nestedKeyPathNotConfigure | |
case keyNotConfigured | |
} | |
private struct DynamicCodingKeys: CodingKey | |
{ | |
// Use for string-keyed dictionary | |
var stringValue: String | |
init?(stringValue: String) | |
{ | |
self.stringValue = stringValue | |
} | |
// Use for integer-keyed dictionary | |
var intValue: Int? | |
init?(intValue _: Int) | |
{ | |
// We are not using this, thus just return nil | |
return nil | |
} | |
} | |
required init(from decoder: Decoder) throws | |
{ | |
guard let nestedKeyValueKeyPath = decoder.userInfo[.nestedKeyUserInfoKey] as? [String] | |
else | |
{ | |
throw DecodeError.nestedKeyPathNotConfigure | |
} | |
guard !nestedKeyValueKeyPath.isEmpty | |
else | |
{ | |
value = try decoder.singleValueContainer().decode(T.self) | |
return | |
} | |
let keyPathLength = nestedKeyValueKeyPath.count | |
var container: KeyedDecodingContainer<DynamicCodingKeys> = try decoder.container(keyedBy: DynamicCodingKeys.self) | |
for k in 0 ..< (keyPathLength - 1) | |
{ | |
let key = nestedKeyValueKeyPath[k] | |
let codingKey = DynamicCodingKeys(stringValue: key)! | |
container = try container.nestedContainer(keyedBy: DynamicCodingKeys.self, forKey: codingKey) | |
} | |
let lastKey = nestedKeyValueKeyPath[keyPathLength - 1] | |
value = try container.decode(T.self, forKey: DynamicCodingKeys(stringValue: lastKey)!) | |
} | |
} | |
public extension CodingUserInfoKey | |
{ | |
static let nestedKeyUserInfoKey = CodingUserInfoKey(rawValue: "Nested.Key")! | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment