Может ли API не понимать мои типы свойств? - PullRequest
0 голосов
/ 12 апреля 2019

Я не знаю, как объяснить ... но есть ощущение, что API знает, как установить строку в имени, но он не знает, как ввести свойства с типом структуры и уже установить другие значения

Есть URL для моего API = "https://cdn.rawgit.com/akabab/superhero-api/0.2.0/api/all.json"

. Поэтому я создал правильную модель, которая принимает нужные мне значения. Но по какой-то причине, когда я печатаю свою константу, она показывает мнеэти свойства отсутствуют, кроме имени.

Вот моя модель:

struct SuperHero: Decodable {

    let name: String?
    let powerstats: PowerStats?
    let appearance: Appearance?
    let biography: Biography?
    let work: Work?
    let images: Images?
}

struct PowerStats: Decodable {

    let intelligence: Int
    let strength: Int
    let speed: Int
    let durability: Int
    let power: Int
    let combat: Int
}

struct Appearance: Codable {

    let gender: Gender
    let race: String?
    let height, weight: [String]
}

enum Gender: String, Codable {

    case empty = "-"
    case female = "Female"
    case male = "Male"
}

struct Biography: Codable {

    let fullName, alterEgos: String
    let aliases: [String]
    let firstAppearance: String
    let publisher: String?
    let alignment: Alignment
}

enum Alignment: String, Codable {

    case bad = "bad"
    case empty = "-"
    case good = "good"
    case neutral = "neutral"
}

struct Work: Codable {

    let occupation, base: String
}

struct Images: Decodable {

    let xs: String
    let sm: String
    let md: String
    let lg: String
}

И я пытаюсь найти данные по моей функции:

func fetchData() {

        guard let url = URL(string: url) else { return }

        request(url).validate().responseJSON { (dataResponse) in

            switch dataResponse.result {

            case .success(let value):

                guard let arrayOfItems = value as? Array<[String : Any]> else { return }

                for dict in arrayOfItems {
                    let superHero = SuperHero(name: dict["name"] as? String,
                                              powerstats: dict["powerstats"] as? PowerStats,
                                              appearance: dict["appearance"] as? Appearance,
                                              biography: dict["biography"] as? Biography,
                                              work: dict["work"] as? Work,
                                              images: dict["images"] as? Images)

                    self.superHeroes.append(superHero)
                }

                DispatchQueue.main.async {
                    self.collectionView.reloadData()
                }

            case.failure(let error):
                print(error)
            }
        }

    }
}

1 Ответ

1 голос
/ 12 апреля 2019

Ошибка возникает из-за невозможности преобразования десериализованного значения словаря JSON в пользовательскую структуру.Вам придется создавать другие структуры, вызывая их init методы, такие как SuperHero.

Поскольку ваши структуры соответствуют Decodable, в любом случае используйте JSONDecoder, просто замените responseJSON на responseData наполучить необработанные данные.

Вы можете объявить все элементы в корневой структуре как необязательные

struct SuperHero: Decodable {

    let name: String
    let powerstats: PowerStats
    let appearance: Appearance
    let biography: Biography
    let work: Work
    let images: Images
}

, и все члены в Images могут быть непосредственно декодированы в URL

struct Images: Decodable {        
    let xs: URL
    let sm: URL
    let md: URL
    let lg: URL
}

func fetchData() {

    guard let url = URL(string: url) else { return }

    request(url).validate().responseData { (dataResponse) in

        switch dataResponse.result {

        case .success(let data):

            do {
                self.superHeroes = try JSONDecoder().decode([SuperHero].self, from: data)
                DispatchQueue.main.async {
                    self.collectionView.reloadData()
                }
            } catch { print(error) }

        case.failure(let error):
            print(error)
        }

   }
}

Чтобы создать дочерние структуры в коде, вы должны создать каждый отдельный экземпляр.Это пример для PowerStats

for dict in arrayOfItems {
    let pwstats = dict["powerstats"] as! [String:Int]
    let powerStat = PowerStats(intelligence: pwstats["intelligence"]!,
                               strength: pwstats["strength"]!,
                               speed: pwstats["speed"]!,
                               durability: pwstats["durability"]!,
                               power: pwstats["power"]!,
                               combat: pwstats["combat"]!)

    let superHero = SuperHero(name: dict["name"] as? String,
                              powerstats: powerStat, ...

Имейте в виду, что большинство словарей имеют [String:Any], что требует дополнительного приведения типов для каждого значения.

...