Ios 如何为动态键创建模型,json解析,swift5

Ios 如何为动态键创建模型,json解析,swift5,ios,json,swift,xcode,codable,Ios,Json,Swift,Xcode,Codable,我正在解析一个json数据,并试图创建一个模型,但不知道如何从json数据(我已经提供)中获取标题和提取属性,因为pageids属性是动态的。请告诉我如何创建模型以使用id(存储在pageID属性中)从页面提取title属性 jsonData的链接 我试了一点,下面是我的代码,但我不认为这是正确的 var ID = "" struct Document:Codable { let batchcomplete:String let query:Quer

我正在解析一个json数据,并试图创建一个模型,但不知道如何从json数据(我已经提供)中获取标题和提取属性,因为
pageids
属性是动态的。请告诉我如何创建模型以使用id(存储在
pageID
属性中)从页面提取
title
属性

jsonData的链接

我试了一点,下面是我的代码,但我不认为这是正确的

var ID = ""
struct Document:Codable {
    
    let batchcomplete:String
    let query:Query
}
struct Query:Codable {
    let normalized:[Normalized]
    
    let pages:Pages
    
    var pageids:[String]{
        didSet{
            ID = oldValue[0]
        }
    }
    
}

struct Normalized:Codable {
    let from:String
    let to:String // it is a name of an flower
}
struct Pages:Codable {
    let id:[Pages2]
    enum CodingKeys:CodingKey {
        case id = "\(ID)"
    }
}
struct Pages2:Codable {
    let title:String // this is an official name of flower
    let extract:String // this is a body
    let thumbnail:Thumbnail
}
struct Thumbnail:Codable {
    let source:String //this is an url for photo
}

映射JSON的模型如下所示:

struct Document: Codable {
    let batchcomplete: String
    let query: Query
}

struct Query: Codable {
    let normalized: [Normalized]
    var pageids: [String]
    let pages: [String: Page]
}

struct Normalized: Codable {
    let from: String
    let to: String
}

struct Page: Codable {
    let title: String
    let extract: String
    let thumbnail: Thumbnail
}
struct Thumbnail: Codable {
    let source: String
}
您可以使用
pageid
数组和
pages
字典访问每个页面:

let decoder = JSONDecoder()
do {
    let decoded = try decoder.decode(Document.self, from: Data(jsonString.utf8))
    decoded.query.pageids.forEach { id in
        guard let page = decoded.query.pages[id] else { return }
        print(page.title)
    }
} catch {
    print(error)
}
然而,我更愿意对模型做一个小的修改,以便更容易访问页面。这将需要自定义执行
Query
struct:

struct Query: Decodable {
    let normalized: [Normalized]
    let pages: [Page]
    
    enum CodingKeys: String, CodingKey {
        case normalized
        case pageids
        case pages
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        normalized = try container.decode([Normalized].self, forKey: .normalized)
        
        let pageids = try container.decode([String].self, forKey: .pageids)
        let pagesDict = try container.decode([String: Page].self, forKey: .pages)
        pages = pageids.compactMap { pagesDict[$0] }
    }
}
然后,访问每个页面就像循环一样简单:

let decoder = JSONDecoder()
do {
    let decoded = try decoder.decode(Document.self, from: Data(jsonString.utf8))
    decoded.query.pages.forEach { page in
        print(page.title)
    }
} catch {
    print(error)
}

映射JSON的模型如下所示:

struct Document: Codable {
    let batchcomplete: String
    let query: Query
}

struct Query: Codable {
    let normalized: [Normalized]
    var pageids: [String]
    let pages: [String: Page]
}

struct Normalized: Codable {
    let from: String
    let to: String
}

struct Page: Codable {
    let title: String
    let extract: String
    let thumbnail: Thumbnail
}
struct Thumbnail: Codable {
    let source: String
}
您可以使用
pageid
数组和
pages
字典访问每个页面:

let decoder = JSONDecoder()
do {
    let decoded = try decoder.decode(Document.self, from: Data(jsonString.utf8))
    decoded.query.pageids.forEach { id in
        guard let page = decoded.query.pages[id] else { return }
        print(page.title)
    }
} catch {
    print(error)
}
然而,我更愿意对模型做一个小的修改,以便更容易访问页面。这将需要自定义执行
Query
struct:

struct Query: Decodable {
    let normalized: [Normalized]
    let pages: [Page]
    
    enum CodingKeys: String, CodingKey {
        case normalized
        case pageids
        case pages
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        normalized = try container.decode([Normalized].self, forKey: .normalized)
        
        let pageids = try container.decode([String].self, forKey: .pageids)
        let pagesDict = try container.decode([String: Page].self, forKey: .pages)
        pages = pageids.compactMap { pagesDict[$0] }
    }
}
然后,访问每个页面就像循环一样简单:

let decoder = JSONDecoder()
do {
    let decoded = try decoder.decode(Document.self, from: Data(jsonString.utf8))
    decoded.query.pages.forEach { page in
        print(page.title)
    }
} catch {
    print(error)
}