json - JSONDecoder 和结构的问题(API 调用)
问题描述
因此,在解析来自 API 的数据时,我遇到了 JSON 解码器的另一个问题。我收到错误“解析 JSON 错误”。我称这个 api 点为:https ://newsapi.org/v2/top-headlines?category=Science&apiKey=afd219a70f3d47f784e588548c0f7810
这是我拨打电话的代码:
var baseURL = "https://newsapi.org/v2/top-headlines?category=\(category)&apiKey=afd219a70f3d47f784e588548c0f7810"
let defaultSession = URLSession(configuration: .default)
if let url = URL(string: baseURL) {
let request = URLRequest(url: url)
let dataTask = defaultSession.dataTask(with: request) { (data, response, error) in
guard error == nil else {
print("error: ", error!)
return
}
guard let data = data else {
print("No data object")
return
}
guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
print("response is: ", response!)
return
}
guard let mime = response?.mimeType, mime == "application/json" else {
print("Wrong MIME type!")
return
}
guard let articles = try? JSONDecoder().decode(ArticleList.self, from: data) else {
print("Error Parsing JSON")
return
}
DispatchQueue.main.async {
self.articles = articles.articles
print(self.articles)
}
}
dataTask.resume()
}
}
这是我的结构:
// This file was generated from JSON Schema using quicktype, do not modify it directly.
// To parse the JSON, add this file to your project and do:
//
// let welcome = try? newJSONDecoder().decode(Welcome.self, from: jsonData)
import Foundation
// MARK: - Welcome
struct ArticleList: Codable {
let status: String
let totalResults: Int
let articles: [Article]
}
// MARK: - Article
struct Article: Codable {
let source: Source
let author: String?
let title: String
let articleDescription: String?
let url: String
let urlToImage: String?
let publishedAt: Date
let content: String
enum CodingKeys: String, CodingKey {
case source, author, title
case articleDescription = "description"
case url, urlToImage, publishedAt, content
}
}
// MARK: - Source
struct Source: Codable {
let id: JSONNull?
let name: String
}
// MARK: - Encode/decode helpers
class JSONNull: Codable, Hashable {
public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool {
return true
}
public var hashValue: Int {
return 0
}
public init() {}
public required init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if !container.decodeNil() {
throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encodeNil()
}
}
我假设我的结构有问题,这很奇怪,因为我是从 quicktype.io 获得的。有任何想法吗?
解决方案
我也认为它可能与结构有关。要验证您的解析问题,请尝试以下操作:
删除这部分代码:
guard let articles = try? JSONDecoder().decode(ArticleList.self, from: data) else {
print("Error Parsing JSON")
return
}
DispatchQueue.main.async {
self.articles = articles.articles
print(self.articles)
}
并使用这个:
do {
let articles = try JSONDecoder().decode(ArticleList.self, from: data)
DispatchQueue.main.async {
self.articles = articles.articles
print(self.articles)
}
} catch {
print(error)
}
这将向您显示在日志窗口中解析的错误。json很大,所以它可能不止一个。解析错误应该是因为某些模型返回某些变量为空。
解决此问题的一种方法是接受一些变量作为可选变量。像这样:
struct ArticleList: Codable {
let status: String?
let totalResults: Int?
let articles: [Article]?
}
但最好的方法是让您知道哪些是可选的。测试 api 并阅读解析错误的日志将帮助您解决这个问题。
我马上看到的一个问题是你的变量Article.publishedAt
它返回一个像这样的字符串:2021-03-01T14:14:00Z
所以正确的对象是字符串,而不是日期。您必须稍后在解析后将其转换为日期。
推荐阅读
- php - 使用 while 循环在 html 表中显示 php 数据
- javascript - 如何从我的 Vue JS 项目的文件夹中导入 JS 文件?
- typescript - Typescript 扩展 DataType 交替无法编译
- jquery - 我可以提供 HTML 来使用 jQuery 填充 div 吗?
- python-3.x - Python:如何将数据框中的“日期时间”替换为仅表示为整数值的日期?
- android-studio - 如何按 day_of_week 更改我的背景图片
- java - 如何在 Android 上管理四个微调器?
- reactjs - 如何使用 react-router-dom 验证路径变量
- php - PHP高效查询mysql数据库
- linq - 如何在 C# EF dbquery 语句中使用 func 进行排序?