Last active
October 12, 2017 16:19
-
-
Save cruinh/8956eda709f5323e6a91153918fa7182 to your computer and use it in GitHub Desktop.
Generic Codable Parsing
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
func parseResponse(data: Data?, response:URLResponse?, completion:(_ decodedResponse: Codable)->() ) { | |
//Handle the first matching response | |
if let decodedResponse = Decoder<User>.decode(data, response) { completion(decodedResponse) ; return } | |
if let decodedResponse = Decoder<Place>.decode(data, response) { completion(decodedResponse) ; return } | |
if let decodedResponse = Decoder<Thing>.decode(data, response) { completion(decodedResponse) ; return } | |
} | |
struct User: Codable, EndpointData { | |
static var endpoint : String { return "/user" } | |
static var detailEndpoint : Bool { return false } //this would be true if the struct was meant for an endpoint like /user/12345 | |
var username : String | |
} | |
struct Place : Codable, EndpointData { | |
static var endpoint : String { return "/place" } | |
static var detailEndpoint : Bool { return false } | |
var address: String | |
} | |
struct Thing : Codable, EndpointData { | |
static var endpoint : String { return "/thing" } | |
static var detailEndpoint : Bool { return false } | |
var weight: Float | |
} | |
protocol EndpointData : Codable { | |
static var endpoint : String {get} | |
static var detailEndpoint : Bool {get} | |
static func matches(response: URLResponse) -> Bool | |
} | |
extension EndpointData { | |
static func matches(response: URLResponse) -> Bool { | |
guard let url : URL = response.url else { return false } | |
let urlString = url.absoluteString | |
if detailEndpoint == false { | |
return urlString.hasSuffix(endpoint) | |
} else { | |
return urlString.contains(endpoint) | |
} | |
return false | |
} | |
} | |
struct Decoder<T:EndpointData> { | |
static func decode(_ data: Data?, _ response: URLResponse?) -> T? { | |
guard let data = data, | |
let response = response, | |
T.matches(response: response) else { return nil } | |
let jsonDecoder = JSONDecoder() | |
do { | |
let result = try jsonDecoder.decode(T.self, from: data) as? T | |
return result | |
} catch { | |
return nil | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment