Last active
December 16, 2021 18:51
-
-
Save jayrhynas/13dba73d996f1690b05427f7fd4405e0 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
protocol CodingKeyRawValue: Hashable, Codable {} | |
extension String: CodingKeyRawValue {} | |
extension Int: CodingKeyRawValue {} | |
@propertyWrapper | |
struct CodableDictionary<Key: Hashable, Value> where Key: RawRepresentable, Key.RawValue: CodingKeyRawValue { | |
var wrappedValue: [Key: Value] | |
init(wrappedValue: [Key: Value]) { | |
self.wrappedValue = wrappedValue | |
} | |
} | |
extension CodableDictionary: Decodable where Key: Decodable, Value: Decodable { | |
init(from decoder: Decoder) throws { | |
let container = try decoder.singleValueContainer() | |
let dict = try container.decode([Key.RawValue: Value].self) | |
self.wrappedValue = try .init(uniqueKeysWithValues: dict.map { (rawKey, value) in | |
guard let key = Key(rawValue: rawKey) else { | |
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid key \"\(rawKey)\"") | |
} | |
return (key, value) | |
}) | |
} | |
} | |
extension CodableDictionary: Encodable where Key: Encodable, Value: Encodable { | |
func encode(to encoder: Encoder) throws { | |
var container = encoder.singleValueContainer() | |
let dict = [Key.RawValue: Value](uniqueKeysWithValues: self.wrappedValue.map { (key, value) in | |
(key.rawValue, value) | |
}) | |
try container.encode(dict) | |
} | |
} | |
This file contains hidden or 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
import Foundation | |
enum KeyType: String, Codable { | |
case toggle, power, level, timer | |
} | |
enum ValueType: Int, Codable { | |
case disabled, enabled | |
} | |
struct Response: Codable { | |
@CodableDictionary | |
private(set) var host: [KeyType: ValueType] | |
} | |
let data = """ | |
{ | |
"host": { | |
"toggle": 1, | |
"power": 1, | |
"level": 1, | |
"timer": 1 | |
} | |
} | |
""".data(using: .utf8)! | |
try print(JSONDecoder().decode(Response.self, from: data)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment