Marvel API Swift4 JSON Декодирование - PullRequest
0 голосов
/ 22 ноября 2018

Я делаю базовое приложение для IOS, основанное на книге Apple "Разработка приложений со Swift".Мое приложение использует Marvel API.Я пытаюсь найти имя и описание героев.
Связь с API работает полностью и была протестирована несколько раз.Проблема не имеет к этому никакого отношения.

Моя проблема в том, что результат JSON 3 раза вложен, я понятия не имею, как этого достичь в Swift 4.

Здесьпример JSON-результата 1 герояВсе Герои могут быть найдены в «результате»

Структура JSON находится здесь

Мой код содержит фатальную ошибку:

Swift.DecodingError.keyNotFound (CodingKeys (stringValue: "results", intValue: nil)

let jsonDecoder = JSONDecoder()
    let task = URLSession.shared.dataTask(with: url) { (data,
        response, error) in
        try! jsonDecoder.decode(CharactersContainer.self, 
from: data!) //error here
        if let data = data,
            let char = try? jsonDecoder.decode(CharactersContainer.self, from: data) {
            print(char.characters)
            print("succes")

        } else {
            print("failed")
        }
    }

Теперь вот мои модели:

import Foundation

struct Character: Codable {
    var name: String
    var description: String
    //var url: Image


    enum CodingKeys: String, CodingKey {
        case name
        case description
        //case url = "thumbnail"

    }
    init(from decoder: Decoder) throws {
        let valueContainer = try decoder.container(keyedBy: CharactersContainer.CodingKeys.self).nestedContainer(keyedBy: Characters.CodingKeys.self, forKey: .characters).nestedContainer(keyedBy: Character.CodingKeys.self, forKey: .characters)
        if let name = try valueContainer.decodeIfPresent(String.self, forKey: CodingKeys.name) {
            self.name = name
        } else {
            self.name = ""
        }
        if let description = try valueContainer.decodeIfPresent(String.self, forKey: CodingKeys.description) {
            self.description = description
        } else {
            self.description = ""
        }

       // self.url = try valueContainer.decode(URL.self, forKey: CodingKeys.url)

    }
}



struct Characters : Decodable{
    var characters : [Character]
    enum CodingKeys: String, CodingKey {
        case characters = "data"
    }
}

struct CharactersContainer : Decodable {
    var characters : Characters
    //var total: Int
    enum CodingKeys: String, CodingKey {
        case characters = "results"
        //case total
    }
}

Понятия не имеючто я сделал неправильно, так как я видел несколько примеров, которые делали то же самое.

Спасибо за регистрацию!

1 Ответ

0 голосов
/ 22 ноября 2018

В JSON data содержит ключ results.При настройке ваших ключей ожидается, что results будет содержать ключ data.

CharactersContainer.CodingKeys.characters должно быть "data"

Characters.CodingKeys.characters должно быть "results"


Редактировать:

В Character есть еще одна проблема.Он пытается получить содержимое с ключом CharactersContainer.CodingKeys.self, но, вероятно, оно должно быть Character.CodingKeys.self

...