Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@pofat
Created November 14, 2019 15:09
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save pofat/1d59d009afa3a0cd572993b38d983deb to your computer and use it in GitHub Desktop.
Save pofat/1d59d009afa3a0cd572993b38d983deb to your computer and use it in GitHub Desktop.
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

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