Skip to content

Instantly share code, notes, and snippets.

@imthath-m
Created February 14, 2021 17:40
Show Gist options
  • Save imthath-m/a1b1760ba33c4525b5647819960926d1 to your computer and use it in GitHub Desktop.
Save imthath-m/a1b1760ba33c4525b5647819960926d1 to your computer and use it in GitHub Desktop.
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