Skip to content

Instantly share code, notes, and snippets.

@protspace
Last active June 12, 2022 09:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save protspace/4e61e6802462c85b670508407a260915 to your computer and use it in GitHub Desktop.
Save protspace/4e61e6802462c85b670508407a260915 to your computer and use it in GitHub Desktop.
Codable for enum with associated values
import Foundation
enum TargetEnum: Codable {
case first(SomeObject)
case second(OtherObject)
enum CodingKeys: CodingKey {
case first
case second
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let key = container.allKeys.first
switch key {
case .first:
var nestedContainer = try container.nestedUnkeyedContainer(forKey: .first)
let object = try nestedContainer.decode(SomeObject.self)
self = .first(object)
case .second:
var nestedContainer = try container.nestedUnkeyedContainer(forKey: .second)
let object = try nestedContainer.decode(OtherObject.self)
self = .second(object)
default:
throw DecodingError.dataCorrupted(
DecodingError.Context(
codingPath: container.codingPath,
debugDescription: "Unabled to decode enum."
)
)
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case .first(let object):
var nestedContainer = container.nestedUnkeyedContainer(forKey: .first)
try nestedContainer.encode(object)
case .second(let object):
var nestedContainer = container.nestedUnkeyedContainer(forKey: .second)
try nestedContainer.encode(object)
}
}
}
struct SomeObject: Codable {
let name: String
}
struct OtherObject: Codable {
let number: Int
}
// Encoding
let anObject = SomeObject(name: "Hello, World!")
let valueToEncode = TargetEnum.first(anObject)
let encoded = try! JSONEncoder().encode(valueToEncode)
print(String(data: encoded, encoding: .utf8)!)
/* OUTPUT:
{"type":"first","name":"Hello, World!"}
*/
// Decoding
let data = """
[{"first":
[{"name":"Hello, World!"}]
},
{"second":
[{"number":1}]
}]
""".data(using: .utf8)!
let decoded = try! JSONDecoder().decode([TargetEnum].self, from: data)
print(decoded)
/* OUTPUT:
[__lldb_expr_23.TargetEnum.first(__lldb_expr_23.SomeObject(name: "Hello, World!")),
__lldb_expr_23.TargetEnum.second(__lldb_expr_23.OtherObject(number: 1))]
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment