Skip to content

Instantly share code, notes, and snippets.

@andr3a88
Created February 27, 2024 17:51
Show Gist options
  • Save andr3a88/38f4fdf62853ea7ce202158033b0ba47 to your computer and use it in GitHub Desktop.
Save andr3a88/38f4fdf62853ea7ce202158033b0ba47 to your computer and use it in GitHub Desktop.
Using array of mixed Encodable types (in Swift)
import UIKit
/// A type eraser to erase the concrete types of your encodable objects
struct AnyEncodable: Encodable {
private let encodeClosure: (Encoder) throws -> Void
init<T: Encodable>(_ value: T) {
encodeClosure = { encoder in
try value.encode(to: encoder)
}
}
func encode(to encoder: Encoder) throws {
try encodeClosure(encoder)
}
}
// Define a common protocol for all encodable objects
protocol Vehicle: Encodable {}
// Conform all your encodable objects to this protocol
struct PetrolCar: Vehicle {
let name: String = "Petrol Car"
let manufacturer: String = "Ford"
let petrolTankCapacity: Int = 50
}
struct ElectricCar: Vehicle {
let name: String = "Electric Car"
let manufacturer: String = "Tesla"
let batteryCapacity: Int = 75
}
struct GasCar: Vehicle {
let name: String = "Gas Car"
let manufacturer: String = "Renault"
let gasTankCapacity: Int = 55
}
struct F1Car: Vehicle {
let name: String = "SF-24"
let manufacturer: String = "Ferrari"
let petrolTankCapacity: Int = 50
let batteryCapacity: Int = 10
let frontWing: Bool = true
let rearWing: Bool = true
}
// APPROACH TO AVOID
struct MixedVehicles: Vehicle {
let name: String
let manufacturer: String
let petrolTankCapacity: Int?
let gasTankCapacity: Int?
let batteryCapacity: Int?
}
// Create an array of type-erased encodable objects
let vehicles: [AnyEncodable] = [
AnyEncodable(PetrolCar()),
AnyEncodable(ElectricCar()),
AnyEncodable(GasCar()),
AnyEncodable(F1Car())
]
do {
let jsonData = try JSONEncoder().encode(vehicles)
print(String(decoding: jsonData, as: UTF8.self))
} catch {
print("Error encoding JSON: \(error)")
}
// OUTPUT:
// [{"petrolTankCapacity":50,"manufacturer":"Ford","name":"Petrol Car"},{"name":"Electric Car","manufacturer":"Tesla","batteryCapacity":75},{"name":"Gas Car","manufacturer":"Renault","gasTankCapacity":55},{"name":"SF-24","manufacturer":"Ferrari","batteryCapacity":10,"petrolTankCapacity":50,"frontWing":true,"rearWing":true}]
@andr3a88
Copy link
Author

OUTPUT:

[
    {
        "petrolTankCapacity": 50,
        "manufacturer": "Ford",
        "name": "Petrol Car"
    },
    {
        "name": "Electric Car",
        "manufacturer": "Tesla",
        "batteryCapacity": 75
    },
    {
        "name": "Gas Car",
        "manufacturer": "Renault",
        "gasTankCapacity": 55
    },
    {
        "name": "SF-24",
        "manufacturer": "Ferrari",
        "batteryCapacity": 10,
        "petrolTankCapacity": 50,
        "frontWing": true,
        "rearWing": true
    }
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment