采用 Swift HTTP POST 并解码 JSON 响应
Taking Swift HTTP POST and Decoding JSON Response
根据之前的一些帮助,我能够构建它以从 swift 平台内提交 API POST 请求。
import Foundation
struct requestbody: Codable {
let data: DataClass
}
// MARK: - DataClass
struct DataClass: Codable {
let slices: [Slice]
let passengers: [Passenger]
let cabinClass: String
enum CodingKeys: String, CodingKey {
case slices, passengers
case cabinClass = "cabin_class"
}
}
// MARK: - Passenger
struct Passenger: Codable {
let type: String
}
// MARK: - Slice
struct Slice: Codable {
let origin, destination, departureDate: String
enum CodingKeys: String, CodingKey {
case origin, destination
case departureDate = "departure_date"
}
}
class APIPost {
func getposts(response: requestbody) -> URLRequest? {
guard let url = URL(string: "https://api.duffel.com/air/offer_requests") else { return nil }
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("beta", forHTTPHeaderField: "Duffel-Version")
request.setValue("Bearer [redacted]", forHTTPHeaderField: "Authorization")
request.httpMethod = "POST"
request.httpBody = try! JSONEncoder().encode(response)
return request
}
但是,我会说,当谈到如何集成此方法以解码 JSON 响应,然后在 UI 中使用时,我有些困惑。我也不能在函数中添加完成参数(添加@escaping),并且相信最好采取此操作并在另一个函数中构建它。任何高水平(或详细)的回复将不胜感激。
谢谢!
使用This generic function for calling Post方法,调用此方法并在完成时传递请求体和响应体,同样在
中添加URL
class func taskForPOSTRequest<RequestType: Encodable, ResponseType: Decodable>(url: URL, responseType: ResponseType.Type, body: RequestType, completion: @escaping (ResponseType?, Error?) -> Void) {
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = try! JSONEncoder().encode(body)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
DispatchQueue.main.async {
completion(nil, error)
}
return
}
let decoder = JSONDecoder()
do {
let responseObject = try decoder.decode(ResponseType.self, from: data)
DispatchQueue.main.async {
completion(responseObject, nil)
}
} catch {
print(error)
}
}
task.resume()
}
创建一个 URLRequest
实例是不够的,您还必须将此请求发送到您的服务器。您可以通过 URLSession
API.
发送
// Notice the change in function signature
func getPost(requestBody: RequestBody, completion: @escaping ((_ posts: [Post]?, _ error: Error?) -> Void)) -> URLRequest? {
// Everything else same up to this point
request.httpBody = try! JSONEncoder().encode(requestBody)
// Send the request to your server
URLSession.shared.dataTask(with: request, completionHandler: { (data, urlResponse, error) in
// Check if there was an error from network/server
if let error = error {
print(error.localizedDescription)
// call completion with error from network/server
completion(nil, error)
return // return early because there was an error
}
// No error if we are, check for data
if let data = data {
do {
// Try decoding your data to your model
let posts = try JSONDecoder().decode([Post].self, from: data)
// call completion with your models array, no error
completion(posts, nil)
}
catch {
// there's a decoding error, call completion with decoding error
completion(nil, error)
}
}
}).resume() // resuming a dataTask is essential, otherwise the call won't be sent to server
return request
}
根据之前的一些帮助,我能够构建它以从 swift 平台内提交 API POST 请求。
import Foundation
struct requestbody: Codable {
let data: DataClass
}
// MARK: - DataClass
struct DataClass: Codable {
let slices: [Slice]
let passengers: [Passenger]
let cabinClass: String
enum CodingKeys: String, CodingKey {
case slices, passengers
case cabinClass = "cabin_class"
}
}
// MARK: - Passenger
struct Passenger: Codable {
let type: String
}
// MARK: - Slice
struct Slice: Codable {
let origin, destination, departureDate: String
enum CodingKeys: String, CodingKey {
case origin, destination
case departureDate = "departure_date"
}
}
class APIPost {
func getposts(response: requestbody) -> URLRequest? {
guard let url = URL(string: "https://api.duffel.com/air/offer_requests") else { return nil }
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("beta", forHTTPHeaderField: "Duffel-Version")
request.setValue("Bearer [redacted]", forHTTPHeaderField: "Authorization")
request.httpMethod = "POST"
request.httpBody = try! JSONEncoder().encode(response)
return request
}
但是,我会说,当谈到如何集成此方法以解码 JSON 响应,然后在 UI 中使用时,我有些困惑。我也不能在函数中添加完成参数(添加@escaping),并且相信最好采取此操作并在另一个函数中构建它。任何高水平(或详细)的回复将不胜感激。
谢谢!
使用This generic function for calling Post方法,调用此方法并在完成时传递请求体和响应体,同样在
中添加URLclass func taskForPOSTRequest<RequestType: Encodable, ResponseType: Decodable>(url: URL, responseType: ResponseType.Type, body: RequestType, completion: @escaping (ResponseType?, Error?) -> Void) {
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = try! JSONEncoder().encode(body)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
DispatchQueue.main.async {
completion(nil, error)
}
return
}
let decoder = JSONDecoder()
do {
let responseObject = try decoder.decode(ResponseType.self, from: data)
DispatchQueue.main.async {
completion(responseObject, nil)
}
} catch {
print(error)
}
}
task.resume()
}
创建一个 URLRequest
实例是不够的,您还必须将此请求发送到您的服务器。您可以通过 URLSession
API.
// Notice the change in function signature
func getPost(requestBody: RequestBody, completion: @escaping ((_ posts: [Post]?, _ error: Error?) -> Void)) -> URLRequest? {
// Everything else same up to this point
request.httpBody = try! JSONEncoder().encode(requestBody)
// Send the request to your server
URLSession.shared.dataTask(with: request, completionHandler: { (data, urlResponse, error) in
// Check if there was an error from network/server
if let error = error {
print(error.localizedDescription)
// call completion with error from network/server
completion(nil, error)
return // return early because there was an error
}
// No error if we are, check for data
if let data = data {
do {
// Try decoding your data to your model
let posts = try JSONDecoder().decode([Post].self, from: data)
// call completion with your models array, no error
completion(posts, nil)
}
catch {
// there's a decoding error, call completion with decoding error
completion(nil, error)
}
}
}).resume() // resuming a dataTask is essential, otherwise the call won't be sent to server
return request
}