I'm trying to create a Codable struct with an [any Protocol] in Swift 5.7
struct Account: Codable {
var id: String
var name: String
var wallets: [any Wallet]
}
protocol Wallet: Codable {
var id: String { get set }
//... other codable properties
}
However, I'm getting these errors even though Wallet conforms to Codable
Type 'Account' does not conform to protocol 'Decodable'
Type 'Account' does not conform to protocol 'Encodable'
Is it possible to make an any conform to Codable?
or is this still not possible with Swift 5.7?
EDIT: As answered, you have to implement your own conformance. This is how I did mine:
protocol Wallet: Identifiable, Codable {
var id: String { get set }
}
struct DigitalWallet: Wallet {
var id: String
// other properties
}
struct CashWallet: Wallet {
var id: String
// other properties
}
struct Account {
var id: String
var name: String
var wallets: [any Wallet]
}
extension Account: Codable {
enum CodingKeys: String, CodingKey {
case id
case name
case digitalWallet
case cashWallet
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
id = try values.decode(String.self, forKey: .id)
name = try values.decode(String.self, forKey: .name)
let dW = try values.decode([DigitalWallet].self, forKey: .digitalWallet)
let cW = try values.decode([CashWallet].self, forKey: .cashWallet)
wallets = []
wallets.append(contentsOf: dW)
wallets.append(contentsOf: cW)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(name, forKey: .name)
var digitalWallet: [DigitalWallet] = []
var cashWallet: [CashWallet] = []
wallets.forEach { wallet in
if wallet is DigitalWallet {
digitalWallet.append(wallet as! DigitalWallet)
} else if wallet is CashWallet {
cashWallet.append(wallet as! CashWallet)
}
}
try container.encode(digitalWallet, forKey: .digitalWallet)
try container.encode(cashWallet, forKey: .cashWallet)
}
}
But I have reverted to just using this instead:
struct Account: Codable {
var id: String
var name: String
var cashWallets: [CashWallet]
var digitalWallets: [DigitalWallet]
}
I worry the performance overhead of any Protocol isn't worth it just to comply to the Dependency Inversion Principle.