Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Codable Either
enum Either<A, B> {
case left(A)
case right(B)
}
extension Either: Decodable where A: Decodable, B: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let a = try? container.decode(A.self) {
self = .left(a)
} else if let b = try? container.decode(B.self) {
self = .right(b)
} else {
fatalError("Must be decoded into \(A.self) or \(B.self)")
}
}
}
extension Either: Encodable where A: Encodable, B: Encodable {
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .left(let a):
try container.encode(a)
case .right(let b):
try container.encode(b)
}
}
}
// Example model
// You can directly decode `Foo` when the value of `bar` is either a `String` or `Bar` object.
struct Foo: Codable {
let bar: Either<String, Bar>
}
struct Bar: Codable {
let name: String
}
@yoxisem544
Copy link

yoxisem544 commented Dec 13, 2019

line 14 如果改成 throw error

throw DecodingError.dataCorruptedError(in: container, debugDescription: "Must be decoded into \(A.self) or \(B.self)")

會不會好一點,不會因為拆到不應該拆的 json 就爆炸

@pofat
Copy link
Author

pofat commented Dec 13, 2019

line 14 如果改成 throw error

throw DecodingError.dataCorruptedError(in: container, debugDescription: "Must be decoded into \(A.self) or \(B.self)")

會不會好一點,不會因為拆到不應該拆的 json 就爆炸

當然 ok 啊 ,我只是寫個示意,throw 是比較正式的做法。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment