弹出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解码错误,不知道还有啥可以尝试的的主要内容,如果未能解决你的问题,请参考以下文章

Swift JSON解码器类型不匹配错误

解析 JSON 错误“预期解码 Array<Any> 但找到了一个数字

玩游戏老弹出 runtime error,不知道是啥原因,只有玩DNF才出来,别的游戏可以正常玩的

快速解码 JSON 数组或字典错误

Plot.ly API 在创建图形时随机抛出 JSON 解码错误

Sencha Touch 错误您正在尝试解码 ASP.NET 中返回的无效 JSON 字符串 HTML 页面