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)
}
}
}