您好,我是Swift的新手,我还是在学习,所以我尝试制作登录控制器并解析json数据(如果它纠正了它解析的ID和东西的json数据),并且如果登录失败,那么json将显示一种信息。我已经为所需的所有值数据制作了一个结构,但是出现了表示为零的错误。
因此,如果登录成功,则为json:
[ { “ id”:891, “ name”:“ User”, “电子邮件”:“ qdpim@immobisp.com”, “状态”:“ 1” }]
如果登录失败,这是json:
[ { “ message”:“登录失败..”, “状态”:“ 0” }]
所以基本上我猜它具有相同的网址?但我不知道我有点卡在这里,我需要帮助
struct login : Codable {
let id : Int
let name : String
let email : String
let status : String
let message : String
init(dictionary : [String : Any]) {
id = (dictionary ["id"] as? Int)!
name = (dictionary ["name"] as? String)!
email = (dictionary ["email"] as? String)!
status = (dictionary ["status"] as? String)!
message = (dictionary ["message"] as? String)!
}
enum CodingKeys : String, CodingKey {
case id = "id"
case name = "name"
case email = "email"
case status = "status"
case message = "message"
}
}
func Login() {
let Email = EmailField.text!
let Pass = PasswordField.text!
print(api)
guard let JsonUrl = URL(string: api) else {return}
URLSession.shared.dataTask(with: JsonUrl) { (data, response, error) in
guard let data = data else {return}
do{
let parsing = try JSONDecoder().decode([login].self, from: data)
print(parsing)
self.Loginnn = parsing
let stats = self.Loginnn.map { $0.status}
if stats.contains("1"){
print("Login Success")
DispatchQueue.main.async {
self.appDelegate.loginSeque()
}
}else if stats.contains("0") {
let action = UIAlertAction(title: "Got It", style: .default, handler: nil)
let alert = UIAlertController(title: "Wrong Email / Password", message: "Please Try Again ", preferredStyle: .alert)
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
// so basicly i wanna run this alert action by search status if its contains "0"
}
}
}catch{
print(error)
}
}.resume()
}
因此,当我尝试测试登录失败时,我不会在日志中的json中显示消息,而是显示此错误
“ keyNotFound(CodingKeys(stringValue:” id“,intValue:nil), Swift.DecodingError.Context(codingPath:[_JSONKey(stringValue:“索引 0“,intValue:0)],debugDescription:“没有与键关联的值 CodingKeys(stringValue:\“ id \”,intValue:nil)(\“ id \”)。“, 底层错误:nil))“
我只是想弹出一些消息或警告,如果由于密码或电子邮件错误或登录失败而导致登录失败.....那么有人可以帮我最好的方法吗?
答案 0 :(得分:1)
您可以如下声明成功和失败响应类型,
struct LoginSuccess: Decodable {
var id: Int
var name: String
var email: String
var status: String
}
struct LoginFailure: Decodable {
var status: String
var message: String
}
然后用作,
guard let JsonUrl = URL(string: api) else { return }
URLSession.shared.dataTask(with: JsonUrl) { (data, response, error) in
guard let data = data else { return }
if let success = try? JSONDecoder().decode([LoginSuccess].self, from: data).first {
GlobalVariable.UserId = String(success.id)
DispatchQueue.main.async {
self.appDelegate.loginSeque()
}
} else if let failure = try? JSONDecoder().decode([LoginFailure].self, from: data).first {
let action = UIAlertAction(title: "Got It", style: .default, handler: nil)
let alert = UIAlertController(title: "Wrong Email / Password", message: failure.message, preferredStyle: .alert)
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
}
}.resume()
答案 1 :(得分:0)
成功响应仅包含键(“ id”,“ name”,“ email”,“ status”)
[{“ id”:891,“ name”:“ User”,“ email”:“ qdpim@immobisp.com”,“ status”:“ 1”}]
并且故障响应仅包含键(“消息”,“状态”)
[{“ message”:“登录失败..”,“ status”:“ 0”}]
如果要对两个JSON响应使用相同的结构,则应将属性设为可选
struct login : Codable {
var id: Int?
var name: String?
var email: String?
var status: String?
var message: String?
}
此外,由于密钥与属性相同,因此如果您使用enum CodingKeys
init
或JSONDecoder().decode
答案 2 :(得分:0)
在这种情况下,我将使用JSONSerialization将数据解码为[[String:Any]],然后查看内容以确定它是哪种消息。
在我的代码中,我假设“状态”项告诉我们是否成功登录,但是例如可以查找“ id”的存在或字典中元素的数量来确定响应类型
do {
let result = try JSONSerialization.jsonObject(with: data) as! [[String: Any]]
if let response = result.first, let status = response["status"] as? String {
if status == "1" {
if let id = response["id"] as? Int {
let ids = String(id)
//...
}
} else {
if let message = response["message"] as? String {
print(message)
}
}
}
} catch {
print(error)
}
以下是您的问题代码中使用的我的解决方案。请注意,我简化了Login结构,因为它仅在登录成功时使用
struct Login {
let id : Int
let name : String
let email : String
}
do {
let result = try JSONSerialization.jsonObject(with: data) as! [[String: Any]]
if let response = result.first, let status = response["status"] as? String {
if status == "1" {
//handle success
let login = Login(id: response["id"] as? Int ?? 0,
name: response["name"] as? String ?? "",
email: response["email"] as? String ?? "")
self.Loginnn = login
DispatchQueue.main.async {
self.appDelegate.loginSeque()
}
} else {
let action = UIAlertAction(title: "Got It", style: .default, handler: nil)
let alert = UIAlertController(title: "Wrong Email / Password", message: "Please Try Again ", preferredStyle: .alert)
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
}
}
} catch {
print(error)
}
答案 3 :(得分:0)
您已经对此有了一个答案(或三个答案),但是我想向您展示如何在不使用JSONSerialization
或推测性解码的情况下做到这一点。
因此,我们有一些LoginSuccess
和LoginFailure
类型要解码:
struct LoginSuccess: Decodable {
var id: Int
var name: String
var email: String
}
struct LoginFailure: Decodable {
var message: String
}
我们想基于status
区分它们,它们与这些类型的字段位于同一容器中。因此,我们创建了一个enum
:
enum LoginResult: Decodable {
case success(LoginSuccess)
case failure(LoginFailure)
enum Keys: CodingKey {
case status
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Keys.self)
if try container.decode(String.self, forKey: .status) == "1" {
self = .success(try LoginSuccess(from: decoder))
} else {
self = .failure(try LoginFailure(from: decoder))
}
}
}
请注意,enum
的{{1}}不会不调用init
。它传递给decoder.decode(LoginSuccess.self)
初始化程序的解码器。与LoginSuccess
相同。这意味着这些初始化程序将从与LoginFailure
字段相同的容器中提取值。
测试:
status
请注意,由于您的示例数据包含在let successData = #"[ { "id": 891, "name": "User", "email": "qdpim@immobisp.com", "status": "1" } ]"#.data(using: .utf8)!
print(try JSONDecoder().decode([LoginResult].self, from: successData))
// Output:
[__lldb_expr_1.LoginResult.success(__lldb_expr_1.LoginSuccess(id: 891, name: "User", email: "qdpim@immobisp.com"))]
let failureData = #"[ { "message": "Login Failed..", "status": "0" } ]"#.data(using: .utf8)!
print(try JSONDecoder().decode([LoginResult].self, from: failureData))
// Output:
[__lldb_expr_1.LoginResult.failure(__lldb_expr_1.LoginFailure(message: "Login Failed.."))]
中,因此我解码了[...]
的数组。