Skip to content

Instantly share code, notes, and snippets.

@nicklockwood nicklockwood/AnyFoo.swift
Last active Oct 30, 2019

Embed
What would you like to do?
POC for serializing heterogeneous array of structs using Codable in Swift
import Foundation
enum FooType: String, Codable {
case bar, baz
}
protocol Foo: Codable {
var type: FooType { get }
}
extension Foo {
func encode(to container: inout SingleValueEncodingContainer) throws {
try container.encode(self)
}
}
struct AnyFoo: Codable {
let value: Foo
init(_ value: Foo) {
self.value = value
}
enum CodingKeys: CodingKey {
case type
}
init(from decoder: Decoder) throws {
var container = try decoder.container(keyedBy: CodingKeys.self)
switch try container.decode(FooType.self, forKey: .type) {
case .bar:
self.init(try Bar(from: decoder))
case .baz:
self.init(try Baz(from: decoder))
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try value.encode(to: &container)
}
}
struct Bar: Foo {
let type = FooType.bar
var bar: Int
}
struct Baz: Foo {
let type = FooType.baz
var baz: String
}
let coder = JSONEncoder()
let decoder = JSONDecoder()
let values: [Foo] = [
Bar(bar: 5),
Baz(baz: "Hello")
]
let typeErasedValues = values.map(AnyFoo.init)
let data = coder.encode(typeErasedValues)
let decodedErasedValues = decoder.decode([AnyFoo].self, from: data)
let decodedValues = decodedErasedValues.map { $0.value }
print((decodedValues[0] as! Bar).bar) // 5
print((decodedValues[1] as! Baz).baz) // Hello
@nicklockwood

This comment has been minimized.

Copy link
Owner Author

nicklockwood commented Sep 17, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.