Last active
March 17, 2021 17:57
-
-
Save nicklockwood/833fabacbc4b2d11ae7c7d4752b8fd18 to your computer and use it in GitHub Desktop.
POC for serializing heterogeneous array of structs using Codable in Swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For comparison, here is the class version: https://gist.github.com/nicklockwood/3f99995a9273b9e3746ec1579276efd9