I'm trying to (at least) decode JSON that looks something like this:
{
"type": "row",
"title": "Hello...",
"subtitle": "...from JSON"
}
However, "type" defines which Codable Type this represents (e.g. "row" to Row
). I've seen many examples where "type" is one value and the rest are nested in a "payload" value like this:
{
"type": "row",
"payload:
{
"title": "Hello...",
"subtitle": "...from JSON"
}
}
But in my scenario, it's flattened. How can I write a custom decoder that can read the type and THEN (re?)decode with that knowledge?
CodePudding user response:
This is a very small variation of the answer I have posted here: https://stackoverflow.com/a/69330151/669586
enum Item: Decodable {
case data1(Data1)
case data2(Data2)
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
// read type first
let type = try container.decode(String.self, forKey: .type)
// using type, continue decoding and save decoded data
switch type {
case "type1":
let data = try Data1(from: decoder)
self = .data1(data)
case "type2":
let data = try Data2(from: decoder)
self = .data2(data)
default:
throw DecodingError.unknownType
}
}
private enum CodingKeys: String, CodingKey {
case type
}
private enum DecodingError: String, Error {
case unknownType
}
}
struct Data1: Decodable {
}
struct Data2: Decodable {
}