将字典(JSON)反序列化为swift对象

时间:2016-11-29 05:49:20

标签: json swift swift3 deserialization

我正在尝试构建一个登录函数(POST方法),结果是一个带有用户详细信息和其他一些细节的JSON。我已经创建了一个类,其中包含我需要在POST调用结果中使用的所有字段。但我面临的问题是将json反序列化为类的对象。有人可以帮我弄这个吗。 (我在SO上看到了类似的问题并尝试使用解决方案解决。我尝试使用var UserDetails = UserDetails(json:jsonString)将json转换为字符串然后转换为swift对象  )

我的代码:

class UserDetails {
    let token:String
    let agent_id: Int
    let user_id:Int
    let company_id:Int
    let affliate_Id:Int
    let role_id:Int
    let username: String
    let surname:String
    let lastname:String

    init(token:String,agent_id: Int,user_id:Int,company_id:Int,affliate_Id:Int,role_id:Int,username: String,surname:String,lastname:String) {
        self.token = token;
        self.agent_id = agent_id;
        self.user_id = user_id;
        self.company_id = company_id;
        self.affliate_Id = affliate_Id;
        self.role_id = role_id;
        self.username = username;
        self.surname = surname;
        self.lastname = lastname;
    } }

我的控制器类:

let task = session.dataTask(with: request as URLRequest) { data, response, error in
                guard data != nil else {
                    print("no data found: \(error)")
                    return
                }

                do {
                    if let json = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary {
                        NSLog("Login SUCCESS");
                        let prefs:UserDefaults = UserDefaults.standard
                        prefs.set(username, forKey: "USERNAME")
                        prefs.set(udid, forKey: "UDID")
                        prefs.synchronize()
                        print("Response: \(json)")

                        //var jsonString = NSString(data: json, encoding: String.Encoding.utf8)! as String
//when I tried to do the above statement, an error is thrown. Cannot convert value of type NSDictionary to expected argument type Data
                        //var person:UserDetails = UserDetails(json: jsonString)

                        self.dismiss(animated: true, completion: nil)
                    } else {
                        let jsonStr = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)// No error thrown, but not NSDictionary
                        print("Error could not parse JSON: \(jsonStr)")
                    }
                } catch let parseError {
                    print(parseError)// Log the error thrown by `JSONObjectWithData`
                    let jsonStr = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
                    print("Error could not parse JSON: '\(jsonStr)'")
                }
            }

            task.resume()

JSON响应:

{
  "user": {
    "token": "ABCDEFGHI",
    "agent_id": 0,
    "user_id": 151,
    "company_id": 1,
    "affiliate_Id": 0,
    "role_id": 1,
    "username": "testman1",
    "surname": "Test",
    "lastname": "man",
  },
  "menu": [
    { .....

有人可以帮助我解决这个问题。 TIA

2 个答案:

答案 0 :(得分:2)

您应该避免使用Foundation类(NSDictionary等)并使用Swift类型。

我还建议您为接受字典的UserDetails类添加一个可用的初始化器:

class UserDetails {
    let token: String
    let agentId: Int
    let userId: Int
    let companyId: Int
    let affliateId: Int
    let roleId: Int
    let username: String
    let surname: String
    let lastname: String

    init?(dictionary: [String:Any]) {

        guard let token = dictionary["token"] as? String,
            let agentId = dictionary["agent_id"] as? Int,
            let userId = dictionary["user_id"] as? Int,
            ...  // And so on 
        else {
            return nil
        }

        self.token = token;
        self.agentId = agentId;
        self.userId = userId;
        self.companyId = companyId;
        self.affliateId = affliateId;
        self.roleId = roleId;
        self.username = username;
        self.surname = surname;
        self.lastname = lastname;
    } 
}

并在您的完成区块中:

 do {
     if let json = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:Any] {

         if let userDict = json["user"] as [String:Any] {
              guard let userObject = UserDetails(dictionary:userDict) else {
                  print("Failed to create user from dictionary")
                  return
              }
              // Do something with userObject
         }
     }

  } catch let parseError {

我也冒昧从你的属性中删除_因为_是icky

答案 1 :(得分:1)

首先,如果使用类型Dictionary的单个参数定义NSDictionary的init方法,则需要使用Swift本机UserDetails而不是[String: Any]。< / p>

class UserDetails {
    var token:String = ""
    var agent_id: Int = 0
    var user_id:Int = 0
    var company_id:Int = 0
    var affliate_Id:Int = 0
    var role_id:Int = 0
    var username: String = ""
    var surname:String = ""
    var lastname:String = ""

    init(userDic: [String: Any]) {

        if let token = user["token"] as? String, let agent_id = user["agent_id"] as? Int,
            let user_id = user["user_id"] as? Int, let company_id = user["company_id"] as? Int,
            let affliate_Id = user["affliate_Id"] as? Int, let role_id = user["role_id"] as? Int,
            let username = user["username"] as? String, let surname = user["surname"] as? String,
            let lastname = user["lastname"] as? String {

                self.token = token;
                self.agent_id = agent_id;
                self.user_id = user_id;
                self.company_id = company_id;
                self.affliate_Id = affliate_Id;
                self.role_id = role_id;
                self.username = username;
                self.surname = surname;
                self.lastname = lastname;
        }

    }
}

现在只需从你的json响应中调用这个init方法。

if let json = try JSONSerialization.jsonObject(with: data!, options: []) as? [String: Any], let userDic = json["user"] as? [String: Any]{
     let userDetails = UserDetails(userDic: userDic)
}