Reputation: 57
I using the Alamofire Framework, but I don't understand why the variables below are empty.
json:
{
"ret": true,
"text": "Oke!",
"data": {
"email": “[email protected]”,
"nev": "text",
"zip": "1234",
"city": "London",
"street": "text",
"phone": "5555555555",
"gdpr": "2"
}
}
UserDataRootClass.swift:
struct UserDataRootClass : Codable {
let data : UserDataData?
let ret : Bool?
let text : String?
enum CodingKeys: String, CodingKey {
case data = "data"
case ret = "ret"
case text = "text"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
data = try? UserDataData(from: decoder)
ret = try values.decodeIfPresent(Bool.self, forKey: .ret)
text = try values.decodeIfPresent(String.self, forKey: .text)
}
}
UserDataData.swift:
struct UserDataData : Codable {
let city : String?
let email : String?
let gdpr : String?
let nev : String?
let phone : String?
let street : String?
let zip : String?
enum CodingKeys: String, CodingKey {
case city = "city"
case email = "email"
case gdpr = "gdpr"
case nev = "nev"
case phone = "phone"
case street = "street"
case zip = "zip"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
city = try values.decodeIfPresent(String.self, forKey: .city)
email = try values.decodeIfPresent(String.self, forKey: .email)
gdpr = try values.decodeIfPresent(String.self, forKey: .gdpr)
nev = try values.decodeIfPresent(String.self, forKey: .nev)
phone = try values.decodeIfPresent(String.self, forKey: .phone)
street = try values.decodeIfPresent(String.self, forKey: .street)
zip = try values.decodeIfPresent(String.self, forKey: .zip)
}
}
NetworkManager.swift:
func postLogin(urlString: String, completion: @escaping (UserDataRootClass?) -> Void) {
Alamofire.request(urlString).response {
response in
guard let data = response.data else { return }
do {
let decoder = JSONDecoder()
let loginRequest = try decoder.decode(UserDataRootClass.self, from: data)
completion(loginRequest)
} catch let error {
print(error)
completion(nil)
}
}
}
LoginViewController.swift:
let networkManager = NetworkManager()
networkManager.postLogin(urlString: "http://demo.com") { (loginRequest) in
if((loginRequest?.ret)!) {
print(loginRequest) // -> for log
print(loginRequest?.data.phone)
}
}
The log:
UserDataRootClass(data: Optional(.UserDataData(gdpr: nil, email: nil, zip: nil, nev: nil, phone: nil, city: nil, street: nil)), ret: Optional(true), text: Optional("Oke!"))
The loginRequest?.ret
, and loginRequest?.text
is good, but loginRequest?.data.email
, loginRequest?.data.zip
... is empty (nil)
Upvotes: 4
Views: 3966
Reputation: 15238
You don't need to declare CodingKeys
enum
when the variable
name's of your type
are same as the json
keys in api response. For example, in your case you have named all variables(inside UserDataRootClass
and UserDataData
) same as their respective json
key so you can remove those enums.
struct UserDataData : Codable {
let city : String?
let email : String?
let gdpr : String?
let nev : String?
let phone : String?
let street : String?
let zip : String?
}
struct UserDataRootClass : Codable {
let data : UserDataData?
let ret : Bool?
let text : String?
}
Also, you don't need to implement init(from decoder: Decoder) throws {
until you have to do some customization on any attribute.
Upvotes: 3