简体   繁体   English

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

[英]Why I can't parse the following json?

I have json response that I need to parse that, according to the https://newsapi.org web site, should look like:我有我需要解析的 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]"
    }, ...]
}

I created structures for parse it我创建了用于解析它的结构

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]
}

And I created class network service 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()
    }
}

In console I have this:在控制台我有这个:

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

Your error is telling you that the JSON was valid, but that it was unable to find any articles key in the response.您的错误告诉您 JSON 有效,但在响应中找不到任何articles键。

I'd suggest including status and message in your definition of Articles and make articles property an optional.我建议在您对Articles的定义中包含statusmessage ,并使articles属性成为可选属性。 The status might not be "ok" . status可能不是"ok" Regardless, articles is obviously absent.无论如何, articles显然是缺席的。

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

For example, if you don't supply a valid key, you'll get a response like例如,如果您不提供有效的密钥,您将收到类似

{
    "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."
}

You may want to handle the case where articles may be absent if there is an error, by making it optional.您可能希望通过将其设为可选来处理出现错误时articles可能不存在的情况。


Unrelated, but the forced unwrapping operator for data is dangerous.无关,但强制解包data操作符是危险的。 If you have some network error, your app will crash.如果您有一些网络错误,您的应用程序将崩溃。 I'd suggest unwrapping it, eg:我建议打开它,例如:

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()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM