为什么我无法解析以下 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
的定义中包括 status
和 message
,并使 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()
}
我有 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
的定义中包括 status
和 message
,并使 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()
}