Created
December 4, 2018 16:59
-
-
Save RoshanNindrai/3154979e15b60a57a14320bf6197def7 to your computer and use it in GitHub Desktop.
Quick and dirty Swift DTO transformation layer
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
// | |
// Transformable.swift | |
// Transformable | |
// | |
// Created by Roshan Nindrai on 10/15/18. | |
// Copyright © 2018 Roshan Nindrai. All rights reserved. | |
// | |
import Foundation | |
import CoreData | |
/// Coder for decoding Resource from NSObject | |
struct Coder { | |
static let decoder = JSONDecoder() | |
static let encoder = JSONEncoder() | |
} | |
protocol Transformable: class { | |
associatedtype Destination: Codable | |
} | |
protocol Transformer { | |
func toDictionary() -> [AnyHashable: Any] | |
} | |
struct Transform<Source: Transformable>: Transformer { | |
let source: Source | |
} | |
extension Transform { | |
func transform<Destination: Codable>() -> Destination? where Destination == Source.Destination { | |
return try? Coder.decoder.decode(Destination.self, | |
from: JSONSerialization.data(withJSONObject: toDictionary(), | |
options: .prettyPrinted)) | |
} | |
func toDictionary() -> [AnyHashable: Any] { | |
let mySource = Mirror(reflecting: source) | |
return mySource.children.reduce(into: [AnyHashable: Any]()) { dict, property in | |
if let propertyName = property.label { | |
if let value = property.value as? Transformer { | |
dict.updateValue(value.toDictionary(), forKey: propertyName) | |
} else { | |
dict.updateValue(property.value, forKey: propertyName) | |
} | |
} | |
} | |
} | |
} | |
struct Address: Codable { | |
let street: String | |
let city: String | |
} | |
struct Person: Codable { | |
let name: String | |
let address: Address | |
} | |
class AddressEntity: Transformable { | |
typealias Destination = Address | |
let street = "1333 powell st" | |
let city = "Emeryville" | |
} | |
class PersonEntity: Transformable { | |
typealias Destination = Person | |
let name: String | |
let address: Transform<AddressEntity> | |
init(name: String, address: Transform<AddressEntity>) { | |
self.name = name | |
self.address = address | |
} | |
} | |
let address = Transform(source: AddressEntity()) | |
let person = Transform(source: PersonEntity(name: "Roshan", address: address)) | |
print(person.transform()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment