如何使用Codable在Swift中解析带有动态文件名的JSON



我正试图将以下JSON解析为一个类,但不知道如何处理这种特殊情况。

以下是api:https://en.wikipedia.org/w/api.php?format=json&action=查询&prop=摘录&exintro=&explaintext=&indexpageids&title=鸟类

我试图获得标题和摘录,但为了做到这一点,它需要我通过唯一的页面ID。我该如何使用可编码协议来实现这一点?

{ 
"batchcomplete": "", 
"query": { 
"normalized": [
{
"from": "bird",
"to": "Bird"
}
],
"pageids": [
"3410"
],
"pages": {
"3410": {
"pageid": 3410,
"ns": 0,
"title": "Bird",
"extract": "..."
}
}
}
}

我的建议是编写一个自定义初始化器:

pages解码为[String:Page]字典,并根据pageids中的值映射内部字典

let jsonString = """
{
"batchcomplete": "",
"query": {
"normalized": [
{
"from": "bird",
"to": "Bird"
}
],
"pageids": [
"3410"
],
"pages": {
"3410": {
"pageid": 3410,
"ns": 0,
"title": "Bird",
"extract": "..."
}
}
}
}
"""
struct Root : Decodable {
let query : Query
}
struct Query : Decodable {
let pageids : [String]
let pages : [Page]
private enum CodingKeys : String, CodingKey { case pageids, pages }
init(from decoder : Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.pageids = try container.decode([String].self, forKey: .pageids)
let pagesData = try container.decode([String:Page].self, forKey: .pages)
self.pages = self.pageids.compactMap{ pagesData[$0] }
}
}
struct Page : Decodable {
let pageid, ns : Int
let title, extract : String
}

let data = Data(jsonString.utf8)
do {
let result = try JSONDecoder().decode(Root.self, from: data)
print(result)
} catch {
print(error)
}

最新更新