I have different types of objects that conform to the same protocol. Currently, I found the way to encode these objects to the array, but not the way to decode them back
There is my Playground
import UIKit
import SceneKit
extension SCNVector3 {
func toArr() -> [Float] {
return [self.x, self.y, self.z]
}
}
extension Array where Element == Float {
func toSCNVector3() -> SCNVector3? {
guard self.count < 3 else { return nil }
return SCNVector3Make(self[0], self[1], self[2])
}
}
protocol Parsable : Codable {
var innerObj: InnerObject? { get set }
var type: Types { get set }
}
class InnerObject: Codable {
var vector: SCNVector3? = SCNVector3.init(3.1, 4.1, 5.1)
enum CodingKeys: CodingKey {
case vector
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(vector?.toArr(), forKey: .vector)
}
init() { }
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
vector = try container.decode([Float].self, forKey: .vector).toSCNVector3()
}
}
enum Types: String, Codable {
case first, second
}
protocol FirstImpl: Parsable {
var name: String? { get set }
}
protocol SecondImpl: Parsable {
var name: String? { get set }
}
struct AnyEncodable: Encodable {
let encodeFunction: (Encoder) throws -> Void
init(_ encodable: Encodable) {
encodeFunction = encodable.encode(to:)
}
func encode(to encoder: Encoder) throws {
try encodeFunction(encoder)
}
}
struct ParcerableDecodable: Decodable {
init(from decoder: Decoder) throws {
var container: UnkeyedDecodingContainer = try decoder.unkeyedContainer()
var obj: Parsable?
while !container.isAtEnd {
obj = try container.decode(FirstImpl.self)
}
}
}
class One: FirstImpl {
var type: Types = .first
var name: String? = "first"
var innerObj: InnerObject? = InnerObject()
enum CodingKeys: CodingKey {
case name, innerObj, type
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(type, forKey: .type)
try container.encode(name, forKey: .name)
try container.encode(innerObj, forKey: .innerObj)
}
init() { }
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
innerObj = try container.decode(InnerObject.self, forKey: .innerObj)
type = try container.decode(Types.self, forKey: .type)
}
}
class Second: SecondImpl {
var type: Types = .second
var innerObj: InnerObject? = InnerObject()
var name: String? = "second"
}
do {
let first: Codable = One()
let second: Codable = Second()
let arr = [first, second]
let data: Data = try JSONEncoder().encode(arr.map(AnyEncodable.init))
let stringFist = String(data: data, encoding: .utf8)!
print(stringFist)
let decoder = JSONDecoder()
let arrayBack: [ParcerableDecodable] = try decoder.decode([ParcerableDecodable].self, from: data)
}
The problem is that these objects conform to the same protocol and there is no way to use a protocol while decoding
Are there any ideas?