在Swift 4.2中解码JSON时出现错误
打算对Array进行解码,但是找到了一个字典。
我的JSON模型:
public struct NewsSource: Equatable, Decodable {
public let id: String?
public let name: String?
public let sourceDescription: String?
public let url: URL?
enum CodingKeys: String, CodingKey {
case id
case name
case sourceDescription = "description"
case url
}
public init(id: String,
name: String,
sourceDescription: String,
url: URL,
category: NewsCategory,
language: NewsLanguage,
country: NewsCountry) {
self.id = id
self.name = name
self.sourceDescription = sourceDescription
self.url = url
} }
我如何获取JSON:
func fetchJSON() {
let urlString = "https://newsapi.org/v2/sources?apiKey=myAPIKey"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, _, err) in
DispatchQueue.main.async {
if let err = err {
print("Failed to get data from url:", err)
return
}
guard let data = data else { return }
print(data)
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
self.Sources = try decoder.decode([NewsSource].self, from: data)
self.tableView.reloadData()
} catch let jsonErr {
print("Failed to decode:", jsonErr)
}
}
}.resume()
}
答案 0 :(得分:1)
如果您查看返回的JSON,则它看起来像这样:
{
"status": "ok",
"sources": [{
"id": "abc-news",
"name": "ABC News",
"description": "Your trusted source for breaking news, analysis, exclusive interviews, headlines, and videos at ABCNews.com.",
"url": "https://abcnews.go.com",
"category": "general",
"language": "en",
"country": "us"
}, {
"id": "abc-news-au",
"name": "ABC News (AU)",
"description": "Australia's most trusted source of local, national and world news. Comprehensive, independent, in-depth analysis, the latest business, sport, weather and more.",
"url": "http://www.abc.net.au/news",
"category": "general",
"language": "en",
"country": "au"
},
...
虽然有一个源数组,但该数组不是根。 JSON的根是带有status
字符串和sources
数组的对象。这就是解码器出现故障的原因。
您需要定义其他结构来处理此问题:
struct NewsResult {
let status: String
let sources: [NewsSource]
}
然后您解码该对象:
let sourceResult = try decoder.decode(NewsResult.self, from: data)
self.sources = sourceResult.sources
答案 1 :(得分:0)
这应该是您的结构:
struct NewsSource: Codable {
let status: String
let sources: [NewsSource]
}
public struct NewsSource: Equatable, Decodable {
public let id: String?
public let name: String?
public let sourceDescription: String?
public let url: URL?
enum CodingKeys: String, CodingKey {
case id
case name
case sourceDescription = "description"
case url
}
public init(id: String,
name: String,
sourceDescription: String,
url: URL,
category: NewsCategory,
language: NewsLanguage,
country: NewsCountry) {
self.id = id
self.name = name
self.sourceDescription = sourceDescription
self.url = url
} }
struct Source: Codable {
let id, name, description: String
let url: String
let category: Category
let language, country: String
}
enum Category: String, Codable {
case business = "business"
case entertainment = "entertainment"
case general = "general"
case health = "health"
case science = "science"
case sports = "sports"
case technology = "technology"
}
然后对其进行解码:
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let newsSource = try? decoder.decode(NewsSource.self, from: data)
self.Sources = newsSource.sources
self.tableView.reloadData()
希望这会有所帮助!