如何为动态键创建模型,json 解析,swift5
How to create a Model for dynamic keys , json parsing ,swift5
我正在解析 json 数据并尝试创建模型,但无法弄清楚如何实现标题并从 json 数据(我提供的数据)中提取属性,因为 pageids
属性 是动态的。请告诉我如何创建模型以使用 id(存储在 pageids
属性)
从页面中提取 title
属性
我试了一下,下面是我的代码,但我认为那不正确
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
}
并且您可以使用 pageids
数组和 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[[=12=]] }
}
}
那么,访问每个页面就像循环一样简单:
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 数据并尝试创建模型,但无法弄清楚如何实现标题并从 json 数据(我提供的数据)中提取属性,因为 pageids
属性 是动态的。请告诉我如何创建模型以使用 id(存储在 pageids
属性)
title
属性
我试了一下,下面是我的代码,但我认为那不正确
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
}
并且您可以使用 pageids
数组和 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[[=12=]] }
}
}
那么,访问每个页面就像循环一样简单:
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)
}