'Codable property within Struct doesn't allow the Struct to conform to Codable [duplicate]

I have a struct that I need to conform to 'Codable'. The struct itself must have an object within it that can also conform to 'Codable'. However, this prevents the struct from conforming to 'Codable'itself.

Example:

import Foundation

struct SignalRMessageBroadcastRequest: Codable {
    let method: String?
    let message: Codable
    let group: String?
}

Is there something I'm missing here that could allow this behavior?

Edit:

As @Sweeper pointed out, at compile time it is unknown what the type of message is. So I have to provide custom encode/decode logic so it can be resolved at runtime. To do this I used the value of the 'method' string to attempt encoding/decoding to different models. I suppose you could also just sequentially try different models until one works.

Solution:


struct SignalRMessageBroadcastRequest: Codable {
    let method: String
    let group: String?
    let message: Codable
    
    enum CodingKeys: CodingKey {
        case method, message, group
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        method = try container.decode(String.self, forKey: .method)
        group = try container.decode(String?.self, forKey: .group)
        if method == "method1" {
            message = try container.decode(PossibleObject1.self, forKey: .message)
        } else if method == "method2" {
            message = try container.decode(PossibleObject2.self, forKey: .message)
        } else {
            throw DecodingError.dataCorruptedError(forKey: .method, in: container, debugDescription: "no suitable config type found for method \(method)!")
        }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        
        try container.encode(method, forKey: .method)
        try container.encode(group, forKey: .method)
        if method == "method1" {
            try container.encode(message as? PossibleObject1, forKey: .message)
        } else if method == "method2" {
            try container.encode(message as? PossibleObject2, forKey: .message)
        }
    }
}


Sources

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

Source: Stack Overflow

Solution Source