我有一个非常奇怪的情况,我使用JSON并认为我可以一直将子字符串化为要访问的数据,但是,它无法按预期工作。
使用QuickType,我可以转换以下JSON:https://kidsuper.fodalabs.com/wp-json/wp/v2/art
到下面。
尝试访问时,似乎应该可以执行.acf.gallery.id
,但是一旦我进入acf.gallery
,它就会说.id
不存在。这很奇怪,但是当我尝试
let temp = imageArray[indexPath.row].acf.gallery.id
Value of type 'GalleryUnion?' has no member 'id'
只是为了好玩,我尝试了这个,也没有运气:
let temp = imageArray[indexPath.row].acf.GalleryUnion.galleryElementArray
Error
:类型为“ Acf”的值没有成员“ GalleryUnion”
我打印.acf.gallery
时的返回是这样的:
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
下面是我要解析的完整代码。有任何想法吗?
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
}
}
答案 0 :(得分:2)
在深入探究数组之前,必须先使用if case,guard case或switch case来打开枚举的包装。
if case .galleryElementArray(let x) = imageArray[indexPath.row].acf.gallery {
print(x.first!.id)
}
答案 1 :(得分:2)
但是,一旦我进入acf.gallery,它就会说.id不存在。这很奇怪
不,不是。根据您的代码,.gallery
应该是GalleryUnion。好吧,GalleryUnion没有.id
。它根本没有任何属性。 GalleryElement具有.id
,但是GalleryUnion不是GalleryElement。因此,我看不出您的惊喜来自何处;这里没有惊喜。
GalleryUnion有个案例。您需要检查这是哪种情况。如果为. galleryElementArray
,则需要提取关联的值。即使那样,您也不会有任何.id
,因为您现在拥有的仍然不是GalleryElement;这是GalleryElements的 array 。
您可以通过定义带有额外计算属性的GalleryUnion来简化此工作,该属性为您获取关联的值:
enum GalleryUnion : Codable {
case bool(Bool)
case galleryElementArray([GalleryElement])
var galleryElements : [GalleryElement]? {
switch self {
case .bool : return nil
case let .galleryElementArray(arr): return arr
}
}
// ... and so on
}
至少,您可以这样说:
act.gallery.galleryElements?.map {$0.id}
...或者您有什么想法。
答案 2 :(得分:1)
因此,GalleryUnion
可以做两件事之一。它既可以.bool(_)
也可以galleryElementArray(_)
。当您要访问实际的基础值时,需要确定其处于哪个状态。
要在Swift中执行此操作,可以使用switch
语句。然后,您可以使用它来访问内部包含的值。也许类似于:
if let gallery = acf.gallery {
switch gallery {
case .galleryElementArray(let values):
values.forEach {
print($0.id)
}
case .bool(_):
break
}
}
您可能希望阅读Enumerations,请查找“关联值”部分