-1

I have a page showing my user information and I want to give the user the ability to update the info . So I have created a update button and then if the user press that button it will send the info to API and get a json back as for the new values . My problem here is that I can not decode that json to my structure . Here is how I send my data :

     var user: Update?
    @IBAction func save_user_info_action(_ sender: UIButton) {
     var me = Me()
    let user_credentials = UserDefaults.standard
    guard let id = user_credentials.value(forKey: userDefaults_info.id.rawValue) else {return}


    let username = self.username_txt.text
    let fullname = self.fullName_txt.text
    let email = self.email_txt.text
    let sex = self.sex_txt.text
    let height = self.height_txt.text
    let weight = self.wight_txt.text
    let age = self.age_txt.text
    let password = self.password_txt.text

    if (username != "" && fullname != "" && email != "" && sex != "" && height != "" && weight != ""){

        let url = URL(string: "\(API.user_info_update.rawValue)\(id)")!
        var request = URLRequest(url: url)
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "PUT"
        let postString = "user_name=\(username!)&email=\(email!)&password=\(password!)&sex=\(sex!)&height=\(height!)&weight=\(weight!)&age=\(age!)&full_name=\(fullname!)"
        request.httpBody = postString.data(using: .utf8)
        let task = URLSession.shared.dataTask(with: request) { data, response, error in


            guard let data = data, error == nil else {
                print("error=\(String(describing: error))")
                return
            }

            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("\(String(describing: response))")
            }

            let responseString = String(data: data, encoding: .utf8)
            print(responseString!)

            guard var result = responseString else { return }


            if let json = try? JSONDecoder().decode(Update.self, from: data){
               self.user = json

                print("username : \(self.user?.userID)")



            }

        }
        task.resume()

and as a result I get the following JSON ==>

{"user_id":13,"email":"jhx@gmail.com","password":"pass","user_name":"jhx","full_name":"no name","sex":"no sex","height":"0","weight":"0","age":"","score":0,"createdAt":"2017-12-10T05:18:42.000Z","updatedAt":"2017-12-11T05:36:58.000Z"}

and also here is my structure that I want to decode the json into ==>

import UIKit

struct Update: Codable { 


    let userID : Int?
    let email : String?
    let password : String?
    let userName : String?
    var fullName:String?
    var sex:String?
    var height:Int?
    var weight:Int?
    var age:Int?
    var score : Int?
    var createdAt:String?
    var updatedAt:String?



    func getUserID () -> Int {
        return self.userID!
    }
    func getScore () -> Int {
        return self.score!
    }


    func getEmail () -> String {
        return self.email!
    }
    func getPassword () -> String {
        return self.password!
    }

    func getUsername () -> String {
        return self.userName!
    }


    func getFullname () -> String {
        return self.fullName!
    }

    func getSex () -> String {
        return self.sex!
    }

    func getHeight () -> Int{
        return self.height!
    }

    func getWeight () -> Int{
        return self.weight!
    }



    func getCreatedAt () -> String {
        return self.createdAt!
    }




    enum CodingKeys: String, CodingKey {
        case userID = "user_id"
        case email
        case password
        case score
        case userName = "user_name"
        case fullName = "full_name"
        case sex
        case height
        case weight
        case age
        case createdAt
        case updatedAt
    }


}

but it doesnt work out . I've tried to debug it and it seems at the line that I have if let json = try? JSONDecoder().decode(Update.self, from: data){ the program will never enter the if statement . Any idea where am I making a mistake ? and how can I fix it ? I am quite new to JSONs in swift ?

Danial Kosarifa
  • 1,044
  • 4
  • 18
  • 51
  • what is printing: print(responseString!) ? – mugx Dec 11 '17 at 06:02
  • Instead of declaring your structure properties variable, declare them as constants and create a new object with the new values if you need to change it. – Leo Dabus Dec 11 '17 at 06:03
  • I've used that to get the received json in my console once I can get result i can remove that – Danial Kosarifa Dec 11 '17 at 06:04
  • He asked what is the JSON response – Leo Dabus Dec 11 '17 at 06:05
  • `{"user_id":13,"email":"jhx@gmail.com","password":"pass","user_name":"jhx","full_name":"no name","sex":"no sex","height":"0","weight":"0","age":"","score":0,"createdAt":"2017-12-10T05:18:42.000Z","updatedAt":"2017-12-11T06:05:56.000Z"}` – Danial Kosarifa Dec 11 '17 at 06:06
  • SO like I said if your json have all properties of your user why do you need to change the existing one? Just create a new one. Btw sex should be a enumeration, not a string – Leo Dabus Dec 11 '17 at 06:07
  • @DanialKosarifa https://stackoverflow.com/questions/46458487/how-to-convert-a-date-string-with-optional-fractional-seconds-using-codable-in-s/46458771#46458771 – Leo Dabus Dec 11 '17 at 06:27

1 Answers1

1

Please read the JSON, all strings are wrapped in double quotes so, height, weight and age are String, not Int.

This struct is sufficient. The functions are redundant if you declare all properties as non-optional

struct Update: Codable {

    enum Sex : Codable, String {
        case female, male, noSex = "no sex"
    }

    let userID: Int
    let email: String
    let password: String
    let userName: String
    let fullName: String
    let sex: Sex
    let height: String
    let weight: String
    let age: String
    let score: Int
    let createdAt: String
    let updatedAt: String

    enum CodingKeys: String, CodingKey {
        case userID = "user_id"
        case email, password, score
        case userName = "user_name"
        case fullName = "full_name"
        case sex, height, weight, age, createdAt, updatedAt
    }
}
vadian
  • 274,689
  • 30
  • 353
  • 361