Search code examples
swiftcodabledecodablemirror

Cannot conform to Decodable when using Mirror(reflecting:)


I'm using Decodable in order to decode some JSON, all properties on this struct have the same structure it's just the JSON contains them in multiple arrays. The code works until I add another property let all = Mirror(reflecting: Sizes.self).children. I'm using this in order to get all the properties so I can loop over the struct to actually injest the data.

The issue I'm having is that when I store all as a constant, the code will not compile and gives me the following error:

Type 'Sizes' does not conform to protocol 'Decodable'

struct SizeJSON: Decodable {
    var name: String
    var width: Double
    var height: Double
}

struct Sizes: Decodable {
    let small: [SizeJSON]
    let medium: [SizeJSON]
    let large: [SizeJSON]
    let all = Mirror(reflecting: Sizes.self).children
}

Solution

  • Mirror's init(reflecting:) initializer needs to pass an instance of your type to work.

    You can accomplish what you are trying using a lazy variable, like this:

    struct Sizes: Decodable {
        let small: [SizeJSON]
        let medium: [SizeJSON]
        let large: [SizeJSON]
        lazy var all: [SizeJSON] = {
            Mirror(reflecting: self).children
                .compactMap { $0.value as? [SizeJSON] }
                .flatMap { $0 }
        }()
    }
    

    That way you can both have access to self instance and avoid for all property to be decoded.