Skip to content

Instantly share code, notes, and snippets.

@Gagan5278
Created January 1, 2021 19:05
Show Gist options
  • Save Gagan5278/dd5d99bea51e64a0682c8f456ca8d0c5 to your computer and use it in GitHub Desktop.
Save Gagan5278/dd5d99bea51e64a0682c8f456ca8d0c5 to your computer and use it in GitHub Desktop.
A Gist to decode SEREVR response if associated keys are not available in each fetch from server.
protocol DefaultSourceValue {
associatedtype Value: Decodable
static var defaultValue: Value {get}
}
enum DefaultValue {} //this will not allow for default init
extension DefaultValue {
@propertyWrapper
struct WrappedValue<Source: DefaultSourceValue> {
typealias Value = Source.Value
var wrappedValue = Source.defaultValue
}
}
extension DefaultValue.WrappedValue: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.wrappedValue = try container.decode(Value.self)
}
}
extension KeyedDecodingContainer {
func decode<T>(_ type: DefaultValue.WrappedValue<T>.Type, forKey key: Key) throws -> DefaultValue.WrappedValue<T> {
try decodeIfPresent(type.self, forKey: key) ?? .init()
}
}
extension DefaultValue {
typealias Source = DefaultSourceValue
typealias List = Decodable & ExpressibleByArrayLiteral
typealias Map = Decodable & ExpressibleByDictionaryLiteral
enum Sources {
enum TRUE: Source {
static var defaultValue : Bool {true}
}
enum FALSE: Source {
static var defaultValue : Bool {false}
}
enum EMPTYSTRING: Source {
static var defaultValue : String {""}
}
enum EMPTYLIST<T: List>: Source {
static var defaultValue: T{[]}
}
enum EMPTYDICTIONARY<T: Map>: Source {
static var defaultValue: T {[:]}
}
}
}
extension DefaultValue {
typealias True = WrappedValue<Sources.TRUE>
typealias False = WrappedValue<Sources.FALSE>
typealias EmptyString = WrappedValue<Sources.EMPTYSTRING>
typealias EmptyList<T: List> = WrappedValue<Sources.EMPTYLIST<T>>
typealias EmptyDictionary<T: Map> = WrappedValue<Sources.EMPTYDICTIONARY<T>>
}
////EXAMPLE MODEL
struct Article: Decodable {
var name: String
@DefaultValue.True var isAvailable: Bool
@DefaultValue.False var isFavourite: Bool
@DefaultValue.EmptyString var author: String
@DefaultValue.EmptyList var versions: [String]
@DefaultValue.EmptyDictionary var availableUserTag : [String: String]
}
// 'isAvailable' , 'versions' keys are not available
let items = ["name": "Gagan", "isFavourite": true, "author" : "Ggaan", "versions": ["1","2","3"], "availableUserTag": ["key": "value"]] as [String : AnyObject]
let jsonData = try! JSONSerialization.data(withJSONObject: items, options: .prettyPrinted)
let decoded = JSONDecoder().decode(Article.self, from: jsonData)
print(decoded)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment