Swift4 urlSession Decodable 中的 POST 方法不起作用(这里出了啥问题?)
Posted
技术标签:
【中文标题】Swift4 urlSession Decodable 中的 POST 方法不起作用(这里出了啥问题?)【英文标题】:POST method in Swift4 urlSession Decodable not working(What goes wrong here?)Swift4 urlSession Decodable 中的 POST 方法不起作用(这里出了什么问题?) 【发布时间】:2018-03-20 04:31:29 【问题描述】:我正在尝试发布 2 个参数(电子邮件:和密码)以从服务器获取包含详细用户信息的响应,我构建 API 来处理此问题并使用 Postman 获得良好响应,但是当我尝试使用Swift4 新的 urlsession JSON 解码和编码,它一直失败,我在解码响应数据时出错。 这是我在使用 Postman 时的 JSON 响应:
"error": "false",
"message": "downloaded",
"UserInfo":
"id": 5,
"email": "abc@hotmail.com",
"lastname": "Bence",
"name": "Mark",
"phone": "1234567",
"add1": "333",
"add2": "444",
"city": "ott",
"postalcode": "tttttt"
我的结构文件:
import UIKit
struct loginPost: Encodable
let email: String
let password: String
struct User: Decodable
let error: String?
let message: String?
let UserInfo: [UserData]
struct UserData: Codable
let id: Int?
let email: String?
let lastname: String?
let name: String?
let phone: String?
let add1: String?
let add2: String?
let city: String
let postalcode: String?
我的功能
func downloadJson()
let url = URL(string: http://192.168.0.10/api/login_hashed.php)
guard let downloadURL = url else return
//POST Req
var request = URLRequest(url: downloadURL)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let newpost = loginPost(email: "abc@hotmail.com", password: "123456")
do
let jsonBody = try JSONEncoder().encode(newpost)
request.httpBody = jsonBody
print(jsonBody)
catch
print("some error")
URLSession.shared.dataTask(with: request) data, urlResponse, error in
guard let data = data, error == nil, urlResponse != nil else
print("something is wrong with url")
return
print("downloaded..")
do
let decoder = JSONDecoder()
let downloaduser = try decoder.decode(User.self, from: data)
self.logmessage = downloaduser.message!
print(self.logmessage)
DispatchQueue.main.async
// self.tableView.reloadData()
catch
print("something wrong with decode")
.resume()
【问题讨论】:
添加您的邮递员代码以及您通过 URLSession 遇到的错误 你的服务器工作正常吗? 是的,服务器工作正常,我可以请求 POST 并从 Postman 获得相应的响应。 URLseesion 执行但返回数据从未解码,它也去 catch routine 。控制台打印 - “下载..” - 在 Urlsession 之后,随后打印 - “解码有问题” 【参考方案1】:终于弄明白了,谢谢。 我只想提一下这个错误的原因并分享我的经验。 主要原因是您发送 JSON 和接收传入响应的方式。您应该确切地知道数据的外观,以便以可接受的方式创建您的结构。 我的返回数据只是简单的 2 行文本和文本数组,我的结构是:
import UIKit
struct loginPost: Encodable
let email: String
let password: String
struct User: Decodable
let error: String?
let message: String?
let UserInfo: [UserData]
struct UserData: Codable
let id: Int?
let email: String?
let lastname: String?
let name: String?
let phone: String?
let add1: String?
let add2: String?
let city: String
let postalcode: String?
我在第 18 行的错误
let UserInfo: [UserData]
应该是
let UserInfo: UserData?
没有方括号。 更重要的一点是,始终尝试通过实现 catch let JsonErr 来捕获解码错误,它会告诉你解码不工作的确切原因。
就我而言:
已下载.. 下载后出现问题 typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [h2h.User.(_E33F61CC43E102744E4EF1B7E9D7EDDE 中的 CodingKeys).UserInfo], debugDescription: "预期解码 Array 但发现了一个 字典代替。”,基础错误:无))
并确保您的服务器 API 接受 JSON 格式的 application/json 和 解码您发送的内容以接收您要查找的内容; php代码服务API
$UserData = json_decode(file_get_contents("php://input"), true);
【讨论】:
【参考方案2】:解码 json 的最简单方法。
必须尝试
struct Welcome: Codable
let error, message: String?
let userInfo: UserInfo?
enum CodingKeys: String, CodingKey
case error, message
case userInfo = "UserInfo"
// MARK: - UserInfo
struct UserInfo: Codable
let id: Int?
let email, lastname, name, phone: String?
let add1, add2, city, postalcode: String?
之后在你的代码中,当你从 api 得到响应然后写
let decoder = JSONDecoder()
let obj = try! decoder.decode(Welcome.self, from: jsonData!)
Print(obj)
【讨论】:
【参考方案3】:列表项
这会起作用你创建的模型是错误的吗
struct loginPost: Encodable
let email: String
let password: String
struct Users:Codable
var error:String?
var message:String?
var UserInfo:UserDetails?
struct UserDetails:Codable
let id: Int?
let email: String?
let lastname: String?
let name: String?
let phone: String?
let add1: String?
let add2: String?
let city: String
let postalcode: String?
class ViewController: UIViewController
override func viewDidLoad()
super.viewDidLoad()
downloadJson()
func downloadJson()
let url = URL(string: "http://192.168.0.10/api/login_hashed.php")
guard let downloadURL = url else return
//POST Req
var request = URLRequest(url: downloadURL)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let newpost = loginPost(email: "abc@hotmail.com", password: "123456")
do
let jsonBody = try JSONEncoder().encode(newpost)
request.httpBody = jsonBody
print(jsonBody)
catch
print("some error")
URLSession.shared.dataTask(with: request) data, urlResponse, error in
guard let data = data, error == nil, urlResponse != nil else
print("something is wrong with url")
return
print("downloaded..")
do
let decoder = JSONDecoder()
let downloaduser = try decoder.decode(Users.self, from: data)
// self.logmessage = downloaduser.message!
// print(self.logmessage)
DispatchQueue.main.async
// self.tableView.reloadData()
catch
print("something wrong with decode")
.resume()
【讨论】:
以上是关于Swift4 urlSession Decodable 中的 POST 方法不起作用(这里出了啥问题?)的主要内容,如果未能解决你的问题,请参考以下文章
如何在 swift4 中使用 Rxalamofire 发送 URL 请求