Swift4 url​​Session Decodable 中的 POST 方法不起作用(这里出了啥问题?)

Posted

技术标签:

【中文标题】Swift4 url​​Session Decodable 中的 POST 方法不起作用(这里出了啥问题?)【英文标题】:POST method in Swift4 urlSession Decodable not working(What goes wrong here?)Swift4 url​​Session 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 url​​Session Decodable 中的 POST 方法不起作用(这里出了啥问题?)的主要内容,如果未能解决你的问题,请参考以下文章

使用 Swift Decode 协议格式化日期

如何在 swift4 中使用 Rxalamofire 发送 URL 请求

推送通知点击获取 url 并在 View Controller , iOS , Swift4.2 中显示

从 URL 加载图像并使用 Swift4 将它们存储在本地

如何从url数组循环下载swift4中的pdf

使用 alamofire 和 Swift4 IOS 获取 XML HTTP url 的响应