Skip to content

Instantly share code, notes, and snippets.

@samrayner
Created October 26, 2021 11:01
Show Gist options
  • Save samrayner/963fc5a9f3ed8a654d5bef217e2e7cfc to your computer and use it in GitHub Desktop.
Save samrayner/963fc5a9f3ed8a654d5bef217e2e7cfc to your computer and use it in GitHub Desktop.
import Foundation
///A type that can be encoded to a string-keyed dictionary.
public protocol DictionaryEncodable: Encodable {}
public protocol DictionaryDecodable: Decodable {}
///A type that can be encoded and decoded to/from a string-keyed dictionary.
public typealias DictionaryCodable = DictionaryEncodable & DictionaryDecodable
extension DictionaryEncodable {
/**
Returns a dictionary representation of the object's properties.
- Parameters:
- jsonEncoder: The encoder to use to encode the object's properties.
- Throws: `EncodingError` if the encoding fails.
- Returns: A dictionary representation of the object's properties.
*/
public func dictionary(jsonEncoder: JSONEncoder = JSONEncoder()) throws -> [String: Any] {
let json = try jsonEncoder.encode(self)
guard let dictionary = try JSONSerialization.jsonObject(with: json, options: .allowFragments) as? [String: Any] else {
throw EncodingError.invalidValue(self, .init(codingPath: [], debugDescription: "Unable to convert to [String: Any]"))
}
return dictionary
}
}
extension DictionaryDecodable {
/**
Attempts to initialize an object from a dictionary of its property values.
- Parameters:
- dictionary: The dictionary containing the object's properties.
- jsonDecoder: The decoder to convert the keys and values to the object.
- Throws: `DecodingError` if decoding fails.
*/
public init(dictionary: [String: Any], jsonDecoder: JSONDecoder = JSONDecoder()) throws {
guard JSONSerialization.isValidJSONObject(dictionary) else {
throw DecodingError.dataCorrupted(.init(codingPath: [], debugDescription: "Dictionary is not a valid JSON object."))
}
let data = try JSONSerialization.data(withJSONObject: dictionary, options: [])
self = try jsonDecoder.decode(Self.self, from: data)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment