Skip to content

Instantly share code, notes, and snippets.

@IanKeen
Last active April 13, 2019 18:37
Show Gist options
  • Save IanKeen/38af598c6989a7034858c2373a3d1cd9 to your computer and use it in GitHub Desktop.
Save IanKeen/38af598c6989a7034858c2373a3d1cd9 to your computer and use it in GitHub Desktop.
Type-safe Encodable Dictionary - useful for building quick dynamic Encodable packets
public struct EncodableDictionary {
typealias EncodingFunction = (inout KeyedEncodingContainer<AnyCodingKey>) throws -> Void
// MARK: - Private Properties
private var data: [String: Any] = [:]
private var encodings: [String: EncodingFunction] = [:]
// MARK: - Lifecycle
public init() { }
// MARK: - Public Functions
public subscript<T: Encodable>(key: String) -> T? {
get { return data[key] as? T }
set { updateEncoding(key: key, newValue: newValue) }
}
// MARK: - Private Functions
private mutating func updateEncoding<T: Encodable>(key: String, newValue: T?) {
data[key] = newValue
encodings[key] = newValue.map { value in
return { try $0.encode(value, forKey: AnyCodingKey(key)) }
}
}
}
extension EncodableDictionary: Encodable {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: AnyCodingKey.self)
for (_, encoding) in encodings {
try encoding(&container)
}
}
}
var dict = EncodableDictionary()
dict["foo"] = 42
dict["bar"] = true
let json = String(data: try JSONEncoder().encode(dict), encoding: .utf8)!)
print(json) // {"bar":true,"foo":42}
@IanKeen
Copy link
Author

IanKeen commented Apr 13, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment