【问题标题】:Trying to return a value from API with JSON尝试使用 JSON 从 API 返回值
【发布时间】:2020-12-06 09:14:28
【问题描述】:

我正在尝试从 newsapi.org/ 获取数据。

parseJSON 返回错误,由于某种原因无法从 NewsData 获取数据。

我认为我的 NewsData 属性有问题,其中 parseJSON func 无法计算出数据。

这里是 JSON(来自 urlString):

{
"status": "ok",
"totalResults": 38,
"articles": [

  {
    "source": {
      "id": "fox-news",
      "name": "Fox News"
    },
    "author": "Ryan Gaydos",
    "title": "Errol Spence Jr. retains welterweight titles in victory over Danny Garcia - Fox News",
    "description": "Errol Spence Jr. defeated Danny Garcia via unanimous decision Saturday night to retain the WBC and IBF welterweight titles.",
    "url": "https://www.foxnews.com/sports/errol-spence-jr-danny-garcia-boxing-2020",
    "urlToImage": "https://static.foxnews.com/foxnews.com/content/uploads/2020/12/Errol-Spence2.jpg",
    "publishedAt": "2020-12-06T05:39:59Z",
    "content": "Errol Spence Jr. defeated Danny Garcia via unanimous decision Saturday night to retain the WBC and IBF welterweight titles.\r\nThe judges scored the fight 116-112, 116-112, 117-111 in 

favor of Spence.\r… [+1417 chars]"
      }
    ]
}

这是我的代码:

NewsData.Swift:

struct NewsData: Codable {
    let articles: [Article]
}

struct Article: Codable {
    let title: String
    let description: String
    let content: String
}

NewsManager.Swift:

func getNews() {
    let urlString = "\(baseURL)&apiKey=\(apiKey)"
    
    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(error)        
            } else {
                if let safeData = data {
                    if let news = self.parseJSON(safeData) {
                        print(news)
                    }
                }
            }
        }
        task.resume()
    }   
}

func parseJSON(_ data: Data) -> String? {
    let encoder = JSONDecoder()
    do {
        let encodedData = try encoder.decode(NewsData.self, from: data)

        let des = encodedData.articles[0].content
        let title = encodedData.articles[0].title
        let content = encodedData.articles[0].content
        
        return content
    } catch {
        print(error)
        return nil
    }
}

}

返回错误是:

valueNotFound(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "articles", intValue: nil), _JSONKey(stringValue: "Index 1", intValue: 1), CodingKeys(stringValue: "content", intValue: nil)], debugDescription: "Expected String value but found null instead.", underlyingError: nil))

【问题讨论】:

  • 查看 JSON 有一个缺少的 ] 用于关闭 articles 数组。而且错误可能也会这样说。
  • 对不起,我错过了]。仍然出现错误。
  • 如果您遇到错误,请将其作为问题的一部分。
  • 你的结构模型遗漏了很多元素。
  • 在我看来,第二篇文章没有 content 值,请在您的结构中将该属性设为可选。

标签: json swift api


【解决方案1】:

DecodingError 是有史以来最精确、最容易理解的错误之一。

请完整阅读。

valueNotFound(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "articles", intValue: nil), _JSONKey(stringValue: "Index 1", intValue: 1), CodingKeys(stringValue: " content", intValue: nil)], debugDescription: "预期的字符串值,但发现为 null。", underlyingError: nil))

有三个重要信息:

  1. 什么:valueNotFound表示某处缺少值

  2. 在哪里:CodingPath 类似于一个键路径,将stringValues 结果连接起来:

    articles[1].content
    

    它指向 articles

    的 second 项中的属性 content
  3. 原因:debugDescription 描述了实际错误:

    • Expected 表示 错误 类型 → 非可选的 String
    • found 表示 正确 类型 → <null> 不是值,需要可选类型

解决方案:将content 声明为可选

struct Article: Codable {
    let title: String
    let description: String
    let content: String?
}

【讨论】:

  • 感谢@vadian 的详细解释,我不明白的是JSON 中的content 属性的值是String!而不是可选的。但是 JSON 中 Article 的第二项中的 source.id 为空。这对强制我使用可选字符串的 Content 属性有何影响?
  • 不知道 JSON 我不知道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-03
  • 1970-01-01
  • 2015-10-05
相关资源
最近更新 更多