Ошибка несоответствия типов URLSession - PullRequest
0 голосов
/ 11 мая 2018

Я получаю ошибку несоответствия типов при попытке анализа json с помощью Swift jSon Decoder.

Я просто не могу найти способ разобрать его нормально.

Ошибка:

typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath:
[CodingKeys(stringValue: "data", intValue: nil), 
CodingKeys(stringValue: "itemArr", intValue: nil), 
CodingKeys(stringValue: "price", intValue: nil)], debugDescription:
"Expected to decode String but found a number instead.",
underlyingError:
nil))

Код декодера:

 func getDealDetails(id : String ,completion : @escaping ()->())
{
    let jsonUrl = "https://androidtest.inmanage.com/api/1.0/android/getDeal_\(id).txt"
    guard let url = URL(string: jsonUrl) else { return }

    URLSession.shared.dataTask(with: url) { (data, response, error) in

        guard let data = data else { return }

        do
        {
            let deal = try JSONDecoder().decode(ResultDetails.self, from: data)
            AppManager.shared.dealToShow = deal.data.itemArr

        }catch
        {
            print("There's an error: \(error)")
        }

        completion()

        }.resume()



}
}

И классы:

Во-первых:

class ResultDetails : Decodable
{
  let data : DataDetails

init(data : DataDetails) {
    self.data = data
}


}

Второе:

class DataDetails : Decodable
{
 let itemArr: ItemArr

init(itemArr: ItemArr) {
    self.itemArr = itemArr
}
}

И в-третьих:

class ItemArr : Decodable
{
let id, title, price, description: String
let image: String
let optionsToShow: Int
let gps: Gps
let website, phone: String

  init(id: String, title: String, price: String, description: String,   image: String, optionsToShow: Int, gps: Gps, website: String, phone: String) {
    self.id = id
    self.title = title
    self.price = price
    self.description = description
    self.image = image
    self.optionsToShow = optionsToShow
    self.gps = gps
    self.website = website
    self.phone = phone
}

Я думаю, что пытался все за последние 6 часов, чтобы исправить это, пожалуйста, помогите!

EDIT:

Я поставил неправильный третий класс. теперь это правильный

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

Сообщение об ошибке неверно. По ссылке JSON и вашим классам это должно быть

CodingKeys (stringValue: "цена" , intValue: nil)], debugDescription: Ожидается декодирование Int, но вместо этого найдена строка / данные. ,

Однако он точно скажет вам, что не так: значение для ключа price является String, а не Int.

Вы должны внимательно прочитать JSON. Формат очень прост. Например, все в двойных кавычках равно String, есть нет исключение.


Ваша структура данных слишком сложна. Используйте структуры и сбросьте инициализаторы. Кстати, есть опечатка ItemsArr против ItemArr и нет ключа orderNum.

Ключ image может быть декодирован как URL. Этого достаточно

struct ResultDetails : Decodable {
    let data : DataDetails
}

struct DataDetails : Decodable {
    let itemArr: ItemArr
}

struct ItemArr : Decodable {
    let id, title: String
    let price: String
    let image: URL
    // let orderNum: Int
}

Укажите CodingKeys, только если вы хотите сопоставить ключи. В вашем случае вы даже можете опустить CodingKeys, вместо этого используйте стратегию convertFromSnakeCase.

decoder.keyDecodingStrategy = .convertFromSnakeCase
0 голосов
/ 11 мая 2018

Да, у вас есть ошибка

let price: Int должно быть let price: String, потому что это строка в Json "price": "896" -> String

Пример для Int "optionsToShow":1 -> thisis Int

Вот полный код, который вы можете использовать

import Foundation
struct ResultDetails: Codable {
    let data: DataDetails
}

struct DataDetails: Codable {
    let itemArr: ItemArr
}

struct ItemArr: Codable {
    let id, title, price, description: String
    let image: String
    let optionsToShow: Int
    let gps: Gps
    let website, phone: String
}

struct Gps: Codable {
    let lat, lon: String
}
// MARK: Convenience initializers

extension ResultDetails {
    init(data: Data) throws {
        self = try JSONDecoder().decode(ResultDetails.self, from: data)
    }

    init(_ json: String, using encoding: String.Encoding = .utf8) throws {
        guard let data = json.data(using: encoding) else {
            throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
        }
        try self.init(data: data)
    }


    func jsonData() throws -> Data {
        return try JSONEncoder().encode(self)
    }

    func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
        return String(data: try self.jsonData(), encoding: encoding)
    }
}
...