I'm trying to decode JSON object where one of the properties can be either array or single object. My idea was to introduce enum with single
and multiple
cases. Simplified code example below:
struct Show: Codable {
var artistBio: ArtistBios?
}
enum ArtistBios: Codable {
case single(ArtistBio)
case multiple([ArtistBio])
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
if container.count != nil {
let value = try container.decode([ArtistBio].self)
self = .multiple(value)
} else {
let value = try container.decode(ArtistBio.self)
self = .single(value)
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
switch self {
case .single(let artistBio):
try container.encode(artistBio)
case .multiple(let artistBios):
try container.encode(artistBios)
}
}
}
struct ArtistBio: Codable {
var name: String
var url: String
}
let jsonStrArray = """
{
"artistBio": [
{
"url": "url_to_pdf1",
"name": "Artist Name 1"
},
{
"url": "url_to_pdf2",
"name": "Artist Name 2"
}
]
}
"""
let jsonStrSingle = """
{
"artistBio": {
"url": "url_to_pdf1",
"name": "Artist Name"
}
}
"""
do {
let show = try JSONDecoder().decode(Show.self, from: jsonStrArray.data(using: .utf8)!)
print("show", show)
} catch (let error) {
print("decode multiple error", error)
}
do {
let show = try JSONDecoder().decode(Show.self, from: jsonStrSingle.data(using: .utf8)!)
print("show", show)
} catch (let error) {
print("decode single error", error)
}
I can't figure out the way how to properly decode my enum object. In both cases for single and array version of input JSON I get this error:
typeMismatch(Swift.Array<Any>,
Swift.DecodingError.Context(codingPath: [
CodingKeys(stringValue: "artistBio", intValue: nil),
_JSONKey(stringValue: "Index 0", intValue: 0)],
debugDescription:
"Expected to decode Array<Any> but found a dictionary instead.",
underlyingError: nil))