Skip to content

Instantly share code, notes, and snippets.

@hamdan
Created April 27, 2019 18:41
Show Gist options
  • Save hamdan/c207bf6567052a988651eeb2e39def67 to your computer and use it in GitHub Desktop.
Save hamdan/c207bf6567052a988651eeb2e39def67 to your computer and use it in GitHub Desktop.
Extensions giving Swift's decodable API type inference super powers
// Private supporting types
private struct AnyCodingKey: CodingKey {
var stringValue: String
var intValue: Int?
init(_ string: String) {
stringValue = string
}
init?(stringValue: String) {
self.stringValue = stringValue
}
init?(intValue: Int) {
self.intValue = intValue
self.stringValue = String(intValue)
}
}
// Safe Decoding Container
public struct SafeDecodingContainer<Base: Decodable>: Decodable {
public let value: Base?
public init(from decoder: Decoder) throws {
do {
let container = try decoder.singleValueContainer()
self.value = try container.decode(Base.self)
} catch {
print("Mapping ERROR: \(error)")
self.value = nil
}
}
}
//Helpers
public extension Decoder {
func decode<T: Decodable>(_ key: String, as type: T.Type = T.self) throws -> T {
return try decode(AnyCodingKey(key), as: type)
}
func decode<T: Decodable, K: CodingKey>(_ key: K, as type: T.Type = T.self) throws -> T {
let container = try self.container(keyedBy: K.self)
return try container.decode(type, forKey: key)
}
func decodeGuard<T: Decodable>(_ key: String) throws -> T? {
return try? self.decodeGuard(T.self, forKey: AnyCodingKey(key))
}
func decodeGuard<T: Decodable, K: CodingKey>(_ type: T.Type, forKey key: K) throws -> T? {
let container = try? self.container(keyedBy: K.self)
return tryOrNil { (try container?.decode(T.self, forKey: key)) }
}
func decodeGuardArray<T: Decodable>(_ key: String) throws -> [T] {
return try decodeGuardArray(T.self, forKey: AnyCodingKey(key))
}
func decodeGuardArray<T: Decodable, K: CodingKey>(_ type: T.Type, forKey key: K) throws -> [T] {
let container = try? self.container(keyedBy: K.self)
let array = tryOrNil { (try container?.decode([T].self, forKey: key)) }
return array?.compactMap { $0 } ?? []
}
}
// example code
public struct SaveDecodeClass: Codable {
public var token: String = ""
public var urlString: String = ""
public init(from decoder: Decoder) throws {
token = try decoder.decodeGuard("token") ?? ""
urlString = try decoder.decodeGuard("urlString") ?? ""
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment