Created
February 14, 2021 17:40
-
-
Save imthath-m/a1b1760ba33c4525b5647819960926d1 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
import Foundation | |
class Vehicle: Codable { | |
var seats: Int = 0 | |
init() { } | |
func move() { } | |
} | |
extension Vehicle { | |
static func decode<Key: CodingKey>(from container: KeyedDecodingContainer<Key>, forKey key: Key) throws -> Vehicle { | |
if let car = try? container.decode(Car.self, forKey: key) { | |
return car | |
} | |
if let plane = try? container.decode(Plane.self, forKey: key) { | |
return plane | |
} | |
return try container.decode(Vehicle.self, forKey: key) | |
} | |
} | |
class Car: Vehicle { | |
var wheels: Int = 4 | |
override func move() { | |
// drive car | |
} | |
override init() { | |
super.init() | |
} | |
enum CodingKeys: String, CodingKey { | |
case capacity, wheels | |
} | |
required init(from decoder: Decoder) throws { | |
let container = try decoder.container(keyedBy: CodingKeys.self) | |
self.wheels = try container.decode(Int.self, forKey: .wheels) | |
try super.init(from: decoder) | |
} | |
override func encode(to encoder: Encoder) throws { | |
var container = encoder.container(keyedBy: CodingKeys.self) | |
try container.encode(wheels, forKey: .wheels) | |
try super.encode(to: encoder) | |
} | |
} | |
class Plane: Vehicle { | |
var wings: Int = 2 | |
override func move() { | |
// fly plane | |
} | |
override init() { | |
super.init() | |
} | |
enum CodingKeys: String, CodingKey { | |
case capacity, wings | |
} | |
required init(from decoder: Decoder) throws { | |
let container = try decoder.container(keyedBy: CodingKeys.self) | |
self.wings = try container.decode(Int.self, forKey: .wings) | |
try super.init(from: decoder) | |
} | |
override func encode(to encoder: Encoder) throws { | |
var container = encoder.container(keyedBy: CodingKeys.self) | |
try container.encode(wings, forKey: .wings) | |
try super.encode(to: encoder) | |
} | |
} | |
class Person: Codable { | |
var name: String | |
var vehicle: Vehicle | |
init(name: String, vehicle: Vehicle) { | |
self.name = name | |
self.vehicle = vehicle | |
} | |
enum CodingKeys: String, CodingKey { | |
case name, vehicle | |
} | |
required init(from decoder: Decoder) throws { | |
let container = try decoder.container(keyedBy: CodingKeys.self) | |
self.name = try container.decode(String.self, forKey: .name) | |
self.vehicle = try Vehicle.decode(from: container, forKey: .vehicle) | |
} | |
} | |
extension Encodable { | |
internal var jsonData: Data? { | |
return try? JSONEncoder().encode(self) | |
} | |
internal var jsonString: String? { | |
do { | |
let encoder = JSONEncoder() | |
encoder.outputFormatting = .prettyPrinted | |
return String(data: try encoder.encode(self), encoding: .utf8) | |
} catch { | |
return nil | |
} | |
} | |
} | |
func test() { | |
let pilot = Person(name: "John", vehicle: Plane()) | |
let driver = Person(name: "David", vehicle: Car()) | |
if let pilotString = pilot.jsonString, | |
let driverString = driver.jsonString { | |
print(pilotString) | |
print(driverString) | |
} | |
if let pilotData = pilot.jsonData, | |
let driverData = driver.jsonData, | |
let decodedPilot = try? JSONDecoder().decode(Person.self, from: pilotData), | |
let decodedDriver = try? JSONDecoder().decode(Person.self, from: driverData) { | |
print("Pilot - \(decodedPilot.name), Plane - \((decodedPilot.vehicle as! Plane).jsonString!)") | |
print("Driver - \(decodedDriver.name), Car - \((decodedDriver.vehicle as! Car).jsonString!)") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment