Created
January 1, 2021 19:05
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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