弹出JSON解码错误,不知道还有啥可以尝试的
Posted
技术标签:
【中文标题】弹出JSON解码错误,不知道还有啥可以尝试的【英文标题】:JSON Decoding error pops up, dunno what else to try弹出JSON解码错误,不知道还有什么可以尝试的 【发布时间】:2020-11-20 22:51:19 【问题描述】:各位,我非常感谢您对 JSON 解码的帮助。我正在尝试从此链接获取 API:http://newsapi.org/v2/top-headlines?apiKey=a16b15f863454928804e218705d0f019+&country=us 我可能犯了一些非常业余的错误。第一次在这里上传问题。求帮助!
这是我的数据管理器
protocol NewsManagerDelegate
func didUpdateNews(news: NewsModel)
import Foundation
struct NewsManager
var delegate: NewsManagerDelegate?
let url = "https://newsapi.org/v2/top-headlines?apiKey=a16b15f863454928804e218705d0f019"
func fetchNews(_ countryName: String)
let newsUrlString = "\(url)+&country=\(countryName)"
performRequest(newsUrlString)
func performRequest(_ urlString: String)
if let url = URL(string: urlString)
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) (data, response, error) in
if error != nil
print("networking error \(error!)")
return
if let safeData = data
if let news = parseJSON(safeData)
delegate?.didUpdateNews(news: news)
task.resume()
func parseJSON(_ newsData: Data) -> NewsModel?
do
let decodedData = try JSONDecoder().decode(NewsData.self, from: newsData)
let sourceName = decodedData.articles[5].source.name
let titleName = decodedData.articles[5].title
let linkToImage = decodedData.articles[5].urlToImage
let news = NewsModel(sourceName: sourceName, titleName: titleName, linkToImage: linkToImage )
return news
catch
print(error)
return nil
和我的数据
import Foundation
struct NewsData: Codable
let totalResults: Int
let articles: [Articles]
struct Articles: Codable
let author: String?
let title: String
let description: String
let urlToImage: String
let source: Source
struct Source: Codable
let name: String
我收到此错误
valueNotFound(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "articles", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "description", intValue: nil)], debugDescription: "Expected String value but found null instead.", underlyingError: nil))
我尝试将一些常量设为可选,但之后根本不会显示任何信息。
【问题讨论】:
您可以查看日志错误并尝试阅读它,它会告诉您导致问题的密钥的所有路径 由于您似乎确实获得了数据,但无法解析它,您应该尝试缩小范围。打印出 JSON 数据并将其缩减为无法解析的单个文章示例。将其作为字符串发布(很可能在“”-引号中以使其更易于阅读)并提供您收到的错误消息。这样人们发现错误的问题就会减少。 【参考方案1】:我只需将属性名称更改为articleDescription
并将其设为可选。如果您想解析publishedAt
日期,您只需将解码器dateDecodingStrategy
属性设置为.iso8601
。除此之外,您没有正确构建您的网址。编写网址时应始终使用URLComponents
,并将您的网址属性类型从String
更改为URL
:
struct Root: Codable
let status: String
let totalResults: Int
let articles: [Article]
struct Article: Codable
let source: Source
let author: String?
let title: String
let articleDescription: String?
let url, urlToImage: URL
let publishedAt: Date
let content: String?
enum CodingKeys: String, CodingKey
case source, author, title, articleDescription = "description", url, urlToImage, publishedAt, content
struct Source: Codable
let id: String?
let name: String
游乐场测试:
func fetchNews(_ countryCode: String)
var urlComponents = URLComponents()
urlComponents.scheme = "https"
urlComponents.host = "newsapi.org"
urlComponents.path = "/v2/top-headlines"
urlComponents.queryItems = [.init(name: "apiKey", value: "a16b15f863454928804e218705d0f019"),
.init(name:"country", value: countryCode)]
if let url = urlComponents.url
performRequest(url)
func performRequest(_ url: URL)
URLSession.shared.dataTask(with: url) data, response, error in
guard let data = data else
print("networking error", error ?? "nil")
return
do
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let root = try decoder.decode(Root.self, from: data)
let articles = root.articles
for article in articles
print("article:", article, terminator: "\n")
catch
print(error)
.resume()
fetchNews("us")
这将打印:
文章:文章(来源:__lldb_expr_111.Source(id:Optional(“cnn”),名称:“CNN”),作者:Optional(“Oliver Darcy,CNN Business”),标题:“Tucker Carlson 反弹告诉我们关于某些特朗普支持者的重要信息 - CNN”,文章描述:无,网址:https://www.cnn.com/2020/11/21/media/tucker-carlson-fox-news-traitor/index.html,urlToImage:https://cdn.cnn.com/cnnnext/dam/assets/201105014450-tucker-carlson-fox-news-presidential-election-fraud-super-tease.jpg,发表时间:2020-11-21 16:11:00 +0000,内容:无) 文章:文章(来源:__lldb_expr_111.Source(id:可选(“今日美国”),名称:“今日美国”),作者:可选(“乔尔香农,格蕾丝豪克”),标题:“冠状病毒更新:唐纳德特朗普Jr. 检测呈阳性;模型估计到 3 月美国有 471,000 人死亡;Cuomo 将获得国际艾美奖 - 今日美国”,文章描述:可选(“Donald Trump Jr. 冠状病毒检测呈阳性。模型预测会有更多死亡。大流行期间的感恩节之前发生过。最新的 COVID 新闻。”),url:https://www.usatoday.com/story/news/health/2020/11/21/covid-news-donald-trump-jr-positive-thanksgiving-travel-not-advised/6367181002/,urlToImage:https://www.gannett-cdn.com/presto/2020/11/21/NSTT/caa3ba8a-8e3c-4b49-82e2-2810caf33d05-Testing3.jpg?crop=1574,886,x0,y80&width=1600&height=800&fit=bounds,发布时间:2020-11-21 15:56:15 +0000,内容:可选(“冠状病毒疫苗可能要几个月才能广泛使用到 2021 年。\r\n今日美国\r\n美国在同一周周五报告了超过 195,000 例新的 COVID-19 新病例的历史新高... [+11662 字符]")) 文章:文章(来源:__lldb_expr_111.来源(id:nil,名称:“CBS Sports”),作者:可选(“”),标题:“克莱姆森与佛罗里达州的比赛在开球前几个小时被推迟,因为球队在是否参加比赛方面存在分歧- CBS Sports”,文章描述:可选(“一名克莱姆森球员对 COVID-19 的晚期阳性检测是突然推迟的原因”),url:https://www.cbssports.com/college-football/news/clemson-vs-florida-state-game-postponed-hours-before-kickoff-as-teams-disagreed-about-whether-to-play/,urlToImage:https://sportshub.cbsistatic.com/i/r/2019/01/31/3cfd9702-8ef4-4f0d-9cc6-2601f4b3ad9c/thumbnail/1200x675/d00f9bb392291c844de43984526b773e/clemson.jpg,发表于:2020-11-21 15 :28:00 +0000,内容:可选(“4 号克莱姆森和佛罗里达州立大学将于东部时间中午在佛罗里达州塔拉哈西开始,这场比赛将标志着老虎队四分卫特雷弗劳伦斯在 COVID 阳性后重返赛场...... [+3139 个字符]")) ......
【讨论】:
您能否解释一下为什么在模型中使用枚举编码键?它到底是做什么用的? 只是为了避免在您的结构中创建属性描述。您可能希望将来使您的结构符合CustomStringConvertible【参考方案2】:文章 - 描述 “预期的字符串值,但发现为空。”
改变
let description: String
到
let description: String?
【讨论】:
由于某种原因,如果我将其设为可选,那么我的“作者”将变为 nil,如果我将“作者”设为 nil,那么我的“urlToImage”将变为 nil。我需要这些数据,我该怎么办?【参考方案3】:它说第一个值没有值,你能发布你得到的 json 响应吗,因为这会很有用。另一种可能是 json 响应的顺序与您正在解码的顺序不同。
您可以将描述更改为可选的,因为这样可以解决问题,但是您将没有描述,因此它不能完全解决问题
let description: String?
【讨论】:
是的,使我的描述成为可选的并没有帮助,因为我需要它,同样出于某种原因,如果我将其设为可选,那么我的作者将变为 nil。另外,我如何获得 json 响应?以上是关于弹出JSON解码错误,不知道还有啥可以尝试的的主要内容,如果未能解决你的问题,请参考以下文章
解析 JSON 错误“预期解码 Array<Any> 但找到了一个数字
玩游戏老弹出 runtime error,不知道是啥原因,只有玩DNF才出来,别的游戏可以正常玩的