Swift JSON Кодируемый тип Missmatch Vice Versa - PullRequest
0 голосов
/ 09 мая 2020

У меня проблема с синтаксическим анализом JSON в Codable Struct.

Я опубликую 2 разные попытки с противоположным поведением.

Попробуйте 1:

var url = URL(string: "https://api.imgflip.com/get_memes")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
    guard let data = data else {
        print("Is NIL")
        return
    }
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let memeData = try! decoder.decode([Int: Generals].self, from: data)
    print(memeData)
}

task.resume()


struct Generals: Codable {
    let success: String
    let data: [Int: Memes]
}

struct Memes: Codable {
    let memes: [MemeDetail]
}

struct MemeDetail: Codable {

    let id: Int
    let name: String
    let url: URL
    let width: Int
    let height: Int
    let box_count: Int
}

Это дает мне следующее сообщение об ошибке:

Неустранимая ошибка: 'попробуйте!' выражение неожиданно вызвало ошибку: Swift.DecodingError.typeMismatch (Swift.Int, Swift.DecodingError.Context (codingPath: [_DictionaryCodingKey (stringValue: "data", intValue: nil)], debugDescription: "Ожидаемый ключ Int, но вместо него найден ключ String . ", lowerError: nil)): файл network.playground, строка 15

Тип Missmatch Ожидается Int, но найдено String.

Если я изменю Decoder Dict на String:

let memeData = try! decoder.decode([String: Generals].self, from: data)

Я получаю противоположное сообщение об ошибке:

[_ JSONKey (stringValue: "success", intValue: nil)], debugDescription: "Ожидается декодирование словаря, но вместо этого найдено число . ", lowerError: nil)): файл network.playground, строка 11

Может ли кто-нибудь дать мне совет, что я делаю неправильно или какую часть мне не хватает?

После ответа JSON:

{
    "success": true,
    "data": {
        "memes": [
            {
                "id": "112126428",
                "name": "Distracted Boyfriend",
                "url": "https://i.imgflip.com/1ur9b0.jpg",
                "width": 1200,
                "height": 800,
                "box_count": 3
            },
            {
                "id": "181913649",
                "name": "Drake Hotline Bling",
                "url": "https://i.imgflip.com/30b1gx.jpg",
                "width": 1200,
                "height": 1200,
                "box_count": 2
            },

Заранее спасибо!

1 Ответ

0 голосов
/ 09 мая 2020

Всегда создавайте кодируемую модель в соответствии с вашим ответом API. В вашем сценарии, я думаю, ваша модель будет такой:

struct Generals: Codable {
    let success: Bool
    let data: Memes
}

struct Memes: Codable {
    let memes: [MemeDetail]
}

struct MemeDetail: Codable {

    let id: String?
    let name: String?
    let url: String?
    let width: Int?
    let height: Int?
    let box_count: Int?
}

и при декодировании из данных декодируйте таким образом.

let memeData = try! decoder.decode(Generals.self, from: data) 
...