I have a really weird case where I took JSON and thought I would be able to substring all the way to the data I want to access, however, it's not working as expected.
Using QuickType, I was able to convert this JSON: https://kidsuper.fodalabs.com/wp-json/wp/v2/art
To the below.
When trying to access, it seems like I should be able to do .acf.gallery.id
however once I get to acf.gallery
, it says .id
does not exist. This is strange but here's what it returns when I try
let temp = imageArray[indexPath.row].acf.gallery.id
Value of type 'GalleryUnion?' has no member 'id'
Just for fun I tried this one and had no luck as well:
let temp = imageArray[indexPath.row].acf.GalleryUnion.galleryElementArray
Error
: Value of type 'Acf' has no member 'GalleryUnion'
The return when I print .acf.gallery
starts like this:
Acf(company: "Season #3", gallery: Optional(weddingszn.GalleryUnion.galleryElementArray([weddingszn.GalleryElement( id: 135, galleryID: 135, title: "1-791x1024", filename: "1-791x1024.jpg", url: "https://kidsuper.fodalabs.com/wp-content/up
Full code is below for what I'm trying to parse. Any ideas?
struct Acf: Codable {
let company: String
let gallery: GalleryUnion?
let tagline: String
let featuredImg: Bool?
enum CodingKeys: String, CodingKey {
case company, gallery, tagline
case featuredImg = "featured_img"
}
}
enum GalleryUnion: Codable {
case bool(Bool)
case galleryElementArray([GalleryElement])
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Bool.self) {
self = .bool(x)
return
}
if let x = try? container.decode([GalleryElement].self) {
self = .galleryElementArray(x)
return
}
throw DecodingError.typeMismatch(GalleryUnion.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for GalleryUnion"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .bool(let x):
try container.encode(x)
case .galleryElementArray(let x):
try container.encode(x)
}
}
}
struct GalleryElement: Codable {
let id, galleryID: Int
let title, filename: String
let url: String
let alt, author, description, caption: String
let name, date, modified: String
let mimeType: MIMEType
let type: TypeEnum
let icon: String
let width, height: Int
let sizes: Sizes
enum CodingKeys: String, CodingKey {
case id = "ID"
case galleryID = "id"
case title, filename, url, alt, author, description, caption, name, date, modified
case mimeType = "mime_type"
case type, icon, width, height, sizes
}
}
So, GalleryUnion
can one of two things. It can either both .bool(_)
or galleryElementArray(_)
. When you want access the actual underlying value, you need to determine which state it's in.
To do this in Swift, you can use a switch
statement. You can then use it to gain access to the internally contained values. Maybe something similar to:
if let gallery = acf.gallery {
switch gallery {
case .galleryElementArray(let values):
values.forEach {
print($0.id)
}
case .bool(_):
break
}
}
You might like to have a read of Enumerations, look for the "Associated Values" sections