为什么我无法解析以下 json?

Why I can't parse the following json?

我有 json 需要解析的响应,根据 https://newsapi.org 网站,应该如下所示:

{
    "status": "ok",
    "totalResults": 4498,
    "articles": [{
        "source": {
            "id": null,
            "name": "Techweekeurope.co.uk"
        },
        "author": null,
        "title": "Top ten cloud service providers for reliability and price",
        "description": "In a time where the reliability and stability of cloud service providers comes into spotlight, we pick our top ten that will help you propel your business to the next level. We recently talked about building your own local network with a Raspberry Pi starter …",
        "url": "https://www.techweekeurope.co.uk/top-ten-cloud-service-providers-reliability-price/",
        "urlToImage": "https://www.techweekeurope.co.uk/wp-content/uploads/2020/01/Cloud-Service-Providers.gif",
        "publishedAt": "2020-01-04T16:17:00Z",
        "content": "In a time where the reliability and stability of cloud service providers comes into spotlight, we pick our top ten that will help you propel your business to the next level. We recently talked about building your own local network with a Raspberry Pi starter … [+4441 chars]"
    }, ...]
}

我创建了用于解析它的结构

import Foundation

struct Article: Codable {
    var source: Source
    var author: String?
    var title: String
    var description: String
    var url: URL
    var urlToImage: URL?
    var content: String

    enum codingKeys: String, CodingKey {
        case source
        case author
        case title
        case description
        case url
        case urlToImage
        case content
    }
}

struct Source: Codable {
    var name: String

}

struct Articles: Codable {
    var articles: [Article]
}

并且我创建了 class 网络服务 class

class NetworkService {

    // MARK: - Methods
    func parseJSON(from url: URL) {

        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            do {
                let decoder = JSONDecoder()

                let articleData = try decoder.decode(Articles.self, from: data!)
                print(articleData.articles.description)
            } catch {
                print(error)
            }
        }
        task.resume()
    }
}

在控制台中我有这个:

keyNotFound(CodingKeys(stringValue: "articles", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"articles\", intValue: nil) (\"articles\").", underlyingError: nil))

您的错误告诉您 JSON 有效,但无法在响应中找到任何 articles 键。

我建议在 Articles 的定义中包括 statusmessage,并使 articles 属性 成为可选的。 status 可能不是 "ok"。无论如何, articles 显然不存在。

struct Articles: Codable {
    let articles: [Article]?
    let status: String
    let message: String?
    let code: String?
}

例如,如果您没有提供有效的密钥,您将收到类似

的响应
{
    "status": "error",
    "code": "apiKeyInvalid",
    "message": "Your API key is invalid or incorrect. Check your key, or go to https://newsapi.org to create a free API key."
}

如果出现错误,您可能希望处理 articles 可能不存在的情况,方法是将其设为可选。


无关,但 data 的强制展开运算符很危险。如果你有一些网络错误,你的应用程序将会崩溃。我建议打开它,例如:

func parseJSON(from url: URL) {

    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        guard let data = data, error == nil else {
            print(error ?? "Unknown error")
            return
        }

        do {
            let articleData = try JSONDecoder().decode(Articles.self, from: data)
            guard let articles = articleData.articles else {
                print("No articles", articleData.status, articleData.message ?? "No message")
                return
            }

            for article in articles {
                print(article.description)
            }
        } catch {
            print(error)
        }
    }
    task.resume()
}