Skip to content

Instantly share code, notes, and snippets.

@jayrhynas
Last active December 16, 2021 18:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jayrhynas/13dba73d996f1690b05427f7fd4405e0 to your computer and use it in GitHub Desktop.
Save jayrhynas/13dba73d996f1690b05427f7fd4405e0 to your computer and use it in GitHub Desktop.
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)
}
}
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