#ios #json #swift
#iOS #json #swift
Вопрос:
ребята, я был бы очень признателен за помощь в декодировании JSON. Я пытаюсь получить API по этой ссылке: http://newsapi.org/v2/top-headlines?apiKey=a16b15f863454928804e218705d0f019 amp;country=сша Возможно, я допустил несколько действительно любительских ошибок. При первой загрузке проблема здесь. Обращаюсь за помощью!
Вот мой DataManager
protocol NewsManagerDelegate {
func didUpdateNews(news: NewsModel)
}
import Foundation
struct NewsManager{
var delegate: NewsManagerDelegate?
let url = "https://newsapi.org/v2/top-headlines?apiKey=a16b15f863454928804e218705d0f019"
func fetchNews(_ countryName: String){
let newsUrlString = "(url) amp;country=(countryName)"
performRequest(newsUrlString)
}
func performRequest(_ urlString: String){
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("networking error (error!)")
return
}
if let safeData = data{
if let news = parseJSON(safeData){
delegate?.didUpdateNews(news: news)
}
}
}
task.resume()
}
}
func parseJSON(_ newsData: Data) -> NewsModel?{
do{
let decodedData = try JSONDecoder().decode(NewsData.self, from: newsData)
let sourceName = decodedData.articles[5].source.name
let titleName = decodedData.articles[5].title
let linkToImage = decodedData.articles[5].urlToImage
let news = NewsModel(sourceName: sourceName, titleName: titleName, linkToImage: linkToImage )
return news
}catch{
print(error)
return nil
}
}
}
и мои данные
import Foundation
struct NewsData: Codable {
let totalResults: Int
let articles: [Articles]
}
struct Articles: Codable{
let author: String?
let title: String
let description: String
let urlToImage: String
let source: Source
}
struct Source: Codable{
let name: String
}
Я получаю эту ошибку
valueNotFound(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "articles", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "description", intValue: nil)], debugDescription: "Expected String value but found null instead.", underlyingError: nil))
Я попытался сделать некоторые константы необязательными, но после этого информация вообще не отображалась.
Комментарии:
1. Вы можете просмотреть ошибку журнала и попытаться прочитать ее, в ней указан весь путь к ключу, вызывающему проблему
2. Поскольку вы, похоже, получаете данные, но у вас возникают проблемы с их анализом, вам следует попытаться уменьшить область видимости. Распечатайте данные JSON и сведите их к одному примеру статьи, который не удалось проанализировать. Опубликуйте его в виде строки (скорее всего, в «»»-кавычках, чтобы его было легче читать) и предоставьте полученное сообщение об ошибке. Таким образом, у людей будет меньше проблем с обнаружением ошибки.
Ответ №1:
Я бы просто изменил имя свойства на articleDescription
и сделал его необязательным. Если вы хотите проанализировать publishedAt
дату, все, что вам нужно, это установить dateDecodingStrategy
для свойства decoder .iso8601
значение . Кроме того, вы неправильно создаете свой URL-адрес. Вы всегда должны использовать URLComponents
при составлении своего URL-адреса и изменять типы свойств URL-адресов с String
на URL
:
struct Root: Codable {
let status: String
let totalResults: Int
let articles: [Article]
}
struct Article: Codable {
let source: Source
let author: String?
let title: String
let articleDescription: String?
let url, urlToImage: URL
let publishedAt: Date
let content: String?
enum CodingKeys: String, CodingKey {
case source, author, title, articleDescription = "description", url, urlToImage, publishedAt, content
}
}
struct Source: Codable {
let id: String?
let name: String
}
Тестирование игровой площадки:
func fetchNews(_ countryCode: String) {
var urlComponents = URLComponents()
urlComponents.scheme = "https"
urlComponents.host = "newsapi.org"
urlComponents.path = "/v2/top-headlines"
urlComponents.queryItems = [.init(name: "apiKey", value: "a16b15f863454928804e218705d0f019"),
.init(name:"country", value: countryCode)]
if let url = urlComponents.url {
performRequest(url)
}
}
func performRequest(_ url: URL) {
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else {
print("networking error", error ?? "nil")
return
}
do {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let root = try decoder.decode(Root.self, from: data)
let articles = root.articles
for article in articles {
print("article:", article, terminator: "n")
}
} catch {
print(error)
}
}.resume()
}
fetchNews("us")
Это выведет:
статья: Статья (источник: __lldb_expr_111.Источник (идентификатор: необязательно («cnn»), имя: «CNN»), автор: Необязательно («Оливер Дарси, CNN Business»), заголовок: «Обратная реакция Такера Карлсона рассказывает нам кое-что важное о некоторых сторонниках Трампа -CNN», Описание статьи: ноль, url: https://www.cnn.com/2020/11/21/media/tucker-carlson-fox-news-traitor/index.html , urlToImage: https://cdn.cnn.com/cnnnext/dam/assets/201105014450-tucker-carlson-fox-news-presidential-election-fraud-super-tease.jpg , опубликованный в: 2020-11-21 16:11:00 0000, содержание: ноль)
статья: Статья (источник: __lldb_expr_111.Источник (идентификатор: Необязательно («usa-today»), название: «USA Today»), автор: необязательно («Джоэл Шеннон, Грейс Хаук»), заголовок: «Обновления по коронавирусу: Дональд Трамп-младший дал положительный результат; модель оценивает 471 тыс. смертей в США к марту; Куомо получит международную премию «Эмми» — USA TODAY», Описание статьи: Необязательно («Дональд Трамп-младший дал положительный результат накоронавирус. Модель предсказывает больше смертей. День благодарения во время пандемии случался и раньше. Последние новости о COVID. «), url: https://www.usatoday.com/story/news/health/2020/11/21/covid-news-donald-trump-jr-positive-thanksgiving-travel-not-advised/6367181002/ , urlToImage: https://www .gannett-cdn.com/presto/2020/11/21/NSTT/caa3ba8a-8e3c-4b49-82e2-2810caf33d05-Testing3.jpg?crop=1574,886,x0,y80amp;width=1600amp;height=800amp;fit=bounds , опубликованный в: 2020-11-21 15:56:15 0000, содержание: Необязательно («Вакцина против коронавируса может стать широко доступной только через несколько месяцев после 2021 года.rnUSA СЕГОДНЯ rN The U.S сообщил о рекордном количестве более 195 000 новых ежедневных случаев COVID-19 в пятницу, на той же неделе, когда … [ 11662 символа]»))
статья: Статья (источник: __lldb_expr_111.Источник (id: nil, название: «CBS Sports»), автор: Необязательно («»), заголовок: «Клемсон против Игра штата Флорида отложена за несколько часов до начала, поскольку команды разошлись во мнениях о том, играть или нет — CBS Sports», Описание статьи: необязательно («Поздний положительный тест игрока Clemson на COVID-19 является причиной резкой отсрочки»), url: https://www.cbssports.com/college-football/news/clemson-vs-florida-state-game-postponed-hours-before-kickoff-as-teams-disagreed-about-whether-to-play/ , urlToImage: https://sportshub.cbsistatic.com/i/r/2019/01/31/3cfd9702-8ef4-4f0d-9cc6-2601f4b3ad9c/thumbnail/1200×675/d00f9bb392291c844de43984526b773e/clemson.jpg , Опубликовано: 2020-11-21 15:28:00 0000, содержимое: необязательно («Нет. 4 Клемсон и штат Флорида должны были стартовать в полдень по восточному времени в Таллахасси, штат Флорида, игра, которая ознаменовала бы возвращение квотербека «Тигров» Тревора Лоуренса в строй после положительного COVID … [ 3139 символов] «)) ……
Комментарии:
1. Не могли бы вы также объяснить, почему вы используете ключи enum coding в модели? Для чего именно он используется?
2. Просто чтобы избежать создания описания свойства в вашей структуре. Возможно, в будущем вы захотите привести свою структуру в соответствие с CustomStringConvertible
Ответ №2:
статьи — описание «Ожидаемое строковое значение, но вместо него найдено значение null».
Изменить
let description: String
Для
let description: String?
Комментарии:
1. По какой-то причине, если я сделаю это необязательным, то мой «автор» станет нулевым, а если я сделаю свой «автор» нулевым, то мой «urlToImage» станет нулевым. Мне нужны эти данные, что я могу сделать?
Ответ №3:
В нем говорится, что в первом значении нет значения, можете ли вы опубликовать ответ json, который вы получаете, поскольку это было бы полезно. Другая возможность может заключаться в том, что ответ json находится в другом порядке, чем тот, который вы декодируете.
Вы могли бы просто изменить описание на необязательное, поскольку это избавило бы от проблемы, но тогда у вас не было бы описания, поэтому оно не полностью решает проблему
let description: String?
Комментарии:
1. Да, сделать мое описание необязательным не помогает, поскольку мне это нужно, также по какой-то причине, если я сделаю это необязательным, мой автор станет нулевым. Кроме того, как мне получить ответ json?