'Swift recursive struct in db cannot solved Codable compliant

Swift recursive struct can be solved by helper struct as given below. Unfortunately, this is not Codable compliant:

class Box<T> {
   let boxed: T
   init(_ thingToBox: T) { boxed = thingToBox }
}

struct ContainerClass: Identifiable, Codable {
    let id: UUID?
    var classname: String
    var parent: Box<ContainerClass>?

    private enum ContainerClassKeys: String, CodingKey {
        case id
        case classname
        case parent
    }
}

Error: Type 'ContainerClass' does not conform to protocol 'Encodable'



Solution 1:[1]

You must make Box conform to Codable.

You can use conditional conformance to only make Box Codable when its generic type T is Codable as well.

final class Box<T> {
    let boxed: T
    init(_ thingToBox: T) { boxed = thingToBox }
}

struct ContainerClass: Identifiable, Codable {
    let id: UUID?
    var classname: String
    var parent: Box<ContainerClass>?

    private enum ContainerClassKeys: String, CodingKey {
        case id
        case classname
        case parent
    }
}

extension Box: Codable where T: Codable {
    convenience init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let boxed = try container.decode(T.self)
        self.init(boxed)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(boxed)
    }
}

Alternatively, if you always want T to be Codable, you can simplify the code to

class Box<T: Codable>: Codable {
    let boxed: T
    init(_ thingToBox: T) { boxed = thingToBox }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dávid Pásztor