【问题标题】: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 数据并将其缩减为无法解析的单个文章示例。将其作为字符串发布(很可能在“”-引号中以使其更易于阅读)并提供您收到的错误消息。这样人们发现错误的问题就会减少。

标签: ios json swift


【解决方案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 响应?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-08
  • 2021-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-26
  • 2012-02-20
相关资源
最近更新 更多