将NULL值添加到httpBody Post请求-REST API-Swift

问题描述 投票:0回答:1

我正在尝试将NULL添加为我的httpBody中的键的值。但是目前仅允许执行[String : String]。我虽然打算将String值更改为Any,但这会在整个RestManager中启动多米诺骨牌效果。我想确定,这样做是可能的。或者,如果还有另一种更直观的方法可以这样做。

谢谢。

我的RestManager:

import Foundation

class RestManager {

var httpBody: Data?

var requestHttpHeaders = RestEntity()

var urlQueryParameters = RestEntity()

var httpBodyParameters = RestEntity()

private func addURLQueryParameters(toURL url: URL) -> URL {
    if urlQueryParameters.totalItems() > 0 {
        guard var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return url }

        var queryItems = [URLQueryItem]()
        for (key, value) in urlQueryParameters.allValues() {
            let item = URLQueryItem(name: key, value: value.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed))
            queryItems.append(item)
        }
        urlComponents.queryItems = queryItems
        guard let updatedURL = urlComponents.url else { return url }
        return updatedURL
    }
    return url
}

private func getHttpBody() -> Data? {
    guard let contentType = requestHttpHeaders.value(forkey: "Content-Type") else { return nil }

    if contentType.contains("application/json") {
        return try? JSONSerialization.data(withJSONObject: httpBodyParameters.allValues(), options: [.prettyPrinted, .sortedKeys])
    } else {
        return httpBody
    }
}

private func prepareRequest(withUrl url: URL?, httpBody: Data?, httpMethod: HTTPMethod) -> URLRequest? {
    guard let url = url else { return nil }
    var request = URLRequest(url: url)
    request.httpMethod = httpMethod.rawValue

    for (header, value) in requestHttpHeaders.allValues() {
        request.setValue(value, forHTTPHeaderField: header)
    }
    request.httpBody = httpBody
    return request
}

func makeRequest(toURL url: URL, withHttpMethod httpMethod: HTTPMethod, completion: @escaping (_ result: Results) -> Void) {

    DispatchQueue.global(qos: .userInitiated).async { [weak self] in
        let targetURL = self?.addURLQueryParameters(toURL: url)
        let httpBody = self?.getHttpBody()

        guard let request = self?.prepareRequest(withUrl: targetURL, httpBody: httpBody, httpMethod: httpMethod) else {
            completion(Results(withError: CustomError.failedToCreateRequest))
            return
        }
        let sessionConfiguration = URLSessionConfiguration.default
        let session = URLSession(configuration: sessionConfiguration)
        let task = session.dataTask(with: request) {(data, response, error) in

            completion(Results(withData: data,
                               response: Response(fromURLResponse: response),
                               error: error))

        }
        task.resume()
    }

}

func getData(fromURL url: URL, completion: @escaping (_ data: Data?) -> Void) {
    DispatchQueue.global(qos: .userInitiated).async {
        let sessionConfiguration = URLSessionConfiguration.default
        let session = URLSession(configuration: sessionConfiguration)
        let task = session.dataTask(with: url, completionHandler: { (data, response, error) in
            guard let data = data else { completion(nil); return }
            completion(data)
        })
        task.resume()
    }
}

}

extension RestManager {

enum HTTPMethod: String {
    case get
    case post
    case put
    case patch
    case delete
}

enum CustomError: Error {
    case failedToCreateRequest
}

struct RestEntity {

    private var values: [String: String] = [ : ]

    mutating func add(value: String, forkey key: String) {
        values[key] = value
    }

    func value(forkey key: String) -> String? {
        return values[key]
    }

    func allValues() -> [String : String] {
        return values
    }

    func totalItems() -> Int {
        return values.count
    }
}

struct Response {

    var response: URLResponse?
    var httpStatusCode: Int = 0
    var headers = RestEntity()

    init(fromURLResponse response: URLResponse?) {
        guard let response = response else { return }
        self.response = response
        httpStatusCode = (response as? HTTPURLResponse)?.statusCode ?? 0

        if let headerFields = (response as? HTTPURLResponse)?.allHeaderFields {
            for (key, value) in headerFields {
                headers.add(value: "\(value)", forkey: "\(key)")
            }
        }
    }

}

struct Results {
    var data: Data?
    var response: Response?
    var error: Error?

    init(withData data: Data?, response: Response?, error: Error?) {
        self.data = data
        self.response = response
        self.error = error
    }

    init(withError error: Error?) {
        self.error = error
    }
}
}

extension RestManager.CustomError: LocalizedError {
public var localizedDescription: String {
    switch self {
    case .failedToCreateRequest: return NSLocalizedString("Unable to create the URLRequest object.", comment: "")
    }
}
}
swift rest api post null
1个回答
0
投票

您首先需要一个字典,该字典的值类型可以保存您的值。类型AnyObject的值不能为nil。因此,类型为[String:AnyObject]的字典的值不能为nil。

如果您有一个字典,其值类型是可选类型,例如[String:AnyObject?],则它可以容纳nil个值。例如,

let x : [String : AnyObject?] = ["foo" : nil]

x["foo"] = nil as AnyObject?
© www.soinside.com 2019 - 2024. All rights reserved.