解码JSON-结果为零,没有错误

问题描述

似乎解码过程停止于在init方法中从容器获取值的时候,甚至没有显示任何错误。我想念什么?


    func getUserInfo(userId: Int,completion: @escaping (User?,Error?) -> Void) {
            
            guard let token = Session.shared.token else { return }
            
            let configuration = URLSessionConfiguration.default
            
            let session =  URLSession(configuration: configuration)
    
            var urlConstructor = URLComponents()
            urlConstructor.scheme = "https"
            urlConstructor.host = "api.vk.com"
            urlConstructor.path = "/method/users.get"
            urlConstructor.queryItems = [
                URLQueryItem(name: "user_ids",value: "\(userId)"),URLQueryItem(name: "fields",value: "bdate"),URLQueryItem(name: "access_token",value: "\(token)"),URLQueryItem(name: "v",value: "5.68")
            ]
            
            let decoder = JSONDecoder()
            
            let task = session.dataTask(with: urlConstructor.url!) { (data,response,error) in
                
                let jsonData = try? JSONSerialization.jsonObject(with: data!,options: JSONSerialization.ReadingOptions.allowFragments)
                debugPrint("jsonData:",jsonData)
                
                guard let dataResponse = data,error == nil else {
                    debugPrint(error?.localizedDescription ?? "Response Error")
                    return }
                
                do {
                    
                    let result = try decoder.decode(User.self,from: dataResponse)
                    debugPrint("result:",result)
                    completion(result,nil)
                    
                } catch (let error) {
                    
                    completion(nil,error)
                }
            }
            
            task.resume()
    
        }

我得到的json数据如下:

"jsonData:" Optional({
    response =     (
                {
            bdate = "22.9.2000";
            "first_name" = Toyota;
            id = 616595796;
            "last_name" = Camry;
        }
    );
})

下面是该结构的代码。解码在以“ self.id”开头的行处停止,并且“ getUserInfo”函数的最终结果为nil。


    struct User: Decodable {
        let id: Int
        let firstName: String
        let lastName: String
        let birthDate: Double
        
        init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            self.id = try values.decode(Int.self,forKey: .id)
            self.firstName = try values.decode(String.self,forKey: .firstName)
            self.lastName = try values.decode(String.self,forKey: .lastName)
            self.birthDate = try values.decode(Double.self,forKey: .birthDate)            
        }
        
    }
    
    enum CodingKeys: String,CodingKey {
        case id
        case firstName = "first_name"
        case lastName = "last_name"
        case birthDate = "bdate"
    }

解决方法

结构中没有什么是可选的,但是JSON缺少两个键。如果您的结构要求所有四个属性都存在,那么除非确实存在所有四个属性,否则您将无法获得该结构的有效实例。

您需要做的是更改您的结构,以使可选属性变为可选属性,并在init方法中使用encodeIfPresent。如果要使用默认值,您甚至可以在此时取消合并。

但是您失败了,因为您的数据与您的结构不匹配。

尝试这样的事情:

struct User: Decodable {
    let id: Int
    let firstName: String?
    let lastName: String?
    let birthDate: Double
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        self.id = try values.decode(Int.self,forKey: .id)
        self.firstName = try values.decodeIfPresent(String.self,forKey: .firstName)
        self.lastName = try values.decodeIfPresent(String.self,forKey: .lastName)
        self.birthDate = try values.decode(Double.self,forKey: .birthDate)
    }
    
    enum CodingKeys: String,CodingKey {
        case id
        case firstName = "first_name"
        case lastName = "last_name"
        case birthDate = "bdate"
    }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...