Last active
September 12, 2017 12:00
-
-
Save cipriantarta/75541ce2391975ef921aa8722e9dc76e to your computer and use it in GitHub Desktop.
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
//: Playground - noun: a place where people can play | |
import UIKit | |
typealias JSON = [String: Any] | |
protocol APIModelProtocol { | |
init?(_ data: JSON) | |
} | |
protocol APISerializerProtocol { | |
associatedtype APIModelType | |
func serialize(_ model: APIModelType) -> JSON | |
func deserialize(_ data: JSON) -> APIModelType | |
} | |
private class _AnyAPISerializer<T>: APISerializerProtocol { | |
typealias APIModelType = T | |
init() { | |
guard type(of: self) != _AnyAPISerializer.self else { | |
fatalError("_AnyAPISerializer<APIModelType> instances can not be created; create a subclass instance instead") | |
} | |
} | |
func serialize(_ model: T) -> JSON { | |
fatalError("Must override") | |
} | |
func deserialize(_ data: JSON) -> T { | |
fatalError("Must override") | |
} | |
} | |
private class _AnyAPISerializerBox<T: APISerializerProtocol>: _AnyAPISerializer<T.APIModelType> { | |
private let base: T | |
init(_ base: T) { | |
self.base = base | |
} | |
override func serialize(_ model: T.APIModelType) -> JSON { | |
return base.serialize(model) | |
} | |
override func deserialize(_ data: JSON) -> T.APIModelType { | |
return base.deserialize(data) | |
} | |
} | |
class AnyAPISerializer<APIModelType>: APISerializerProtocol { | |
private let box: _AnyAPISerializer<APIModelType> | |
init<Concrete: APISerializerProtocol>(_ concrete: Concrete) where Concrete.APIModelType == APIModelType { | |
box = _AnyAPISerializerBox(concrete) | |
} | |
func serialize(_ model: APIModelType) -> JSON { | |
return box.serialize(model) | |
} | |
func deserialize(_ data: JSON) -> APIModelType { | |
return box.deserialize(data) | |
} | |
} | |
//================================================ | |
class MyModel: APIModelProtocol { | |
var name: String? | |
required init!(_ data: JSON) { | |
self.name = data["name"] as? String | |
} | |
} | |
class MyModelSerializer: APISerializerProtocol { | |
typealias APIModelType = MyModel | |
func serialize(_ model: MyModel) -> JSON { | |
return ["name": model.name!] | |
} | |
func deserialize(_ data: JSON) -> MyModel { | |
return MyModel(data) | |
} | |
} | |
class APIResponse { | |
private let data: Data | |
init(_ data: Data) { | |
self.data = data | |
} | |
func json(_ serializer: AnyAPISerializer<Any>) -> APIModelProtocol? { | |
guard let obj = try? JSONSerialization.jsonObject(with: self.data), let result = obj as? APIModelProtocol else { | |
return nil | |
} | |
return result | |
} | |
} | |
let serializer = AnyAPISerializer(MyModelSerializer()) | |
let response = APIResponse(data) | |
let data = try! JSONSerialization.data(withJSONObject: ["name": "Test"]) | |
response.json(serializer) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment