简体   繁体   中英

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:

{
    "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))

Your error is telling you that the JSON was valid, but that it was unable to find any articles key in the response.

I'd suggest including status and message in your definition of Articles and make articles property an optional. The status might not be "ok" . Regardless, articles is obviously absent.

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.


Unrelated, but the forced unwrapping operator for data is dangerous. 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()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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