【问题标题】:URLSession Type Mismatch ErrorURLSession 类型不匹配错误
【发布时间】:2018-05-11 16:14:18
【问题描述】:

我在尝试使用 Swift json 解码器解析 json 时遇到类型不匹配错误。

我就是找不到正常解析的方法。

错误:

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 小时内尝试了所有方法来修复它,请帮忙!

编辑:

我放错了三等舱。现在是正确的

【问题讨论】:

    标签: json swift jsondecoder


    【解决方案1】:

    错误信息是错误的。根据 JSON 链接和你的类,它应该是

    CodingKeys(stringValue: "price", intValue: nil)], debugDescription: 应解码 Int,但找到了一个字符串/数据。

    但是它会告诉你究竟出了什么问题:键 price 的值是 String 而不是 Int

    您必须仔细阅读 JSON。格式非常简单。例如双引号中的everythingString没有例外。


    你的数据结构太复杂了。使用结构并删除初始化程序。顺便说一句,ItemsArrItemArr 有一个错字,并且没有键 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
    

    【讨论】:

    • 你好,谢谢,我不小心把错误的代码放在了第三课。现在我修好了,你能再看看吗?这里的价格是字符串
    • 看起来正确。再次不要使用类。无论如何,解码器都不会调用那些初始化程序。并将imagewebsite 解码为URL
    • 我用了 Strucks,还是一样的问题: TypeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "itemArr ", intValue: nil), CodingKeys(stringValue: "price", intValue: nil)], debugDescription: "本应解码字符串,但找到了一个数字。",底层错误:nil))
    • 链接中的 JSON 和我建议的结构确实有效。那么真正的 JSON 就不一样了。此错误消息显示键 price 的值是 Int
    • 我仔细检查了,你是对的,价格是不小心串起来的。
    【解决方案2】:

    是的,你有一个错误

    let price: Int 应该是let price: String,因为它是 Json 中的字符串 "price": "896" --> String

    例如 Int "optionsToShow":1 --> 这是 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)
        }
    }
    

    【讨论】:

    • 嘿,谢谢,我不小心在第三课放错了代码。现在我修好了,你能再看看吗?这里的价格是字符串
    • 是的,现在可以了,只是不要忘记添加GPS class or struct
    • 我用了 Strucks,还是一样的问题: TypeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "itemArr ", intValue: nil), CodingKeys(stringValue: "price", intValue: nil)], debugDescription: "本应解码字符串,但找到了一个数字。",底层错误: nil))
    • 慢慢地你有上面的所有代码检查有什么区别,上面的代码效果很好
    • 我应该将所有结构放在我正在编写子解析代码的同一个地方,还是我可以为每个结构创建一个单独的文件?我应该把 ResultDetails 扩展放在哪里?
    猜你喜欢
    • 2013-01-16
    • 2014-02-05
    • 2018-06-08
    • 2012-02-16
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多