Swift3中如何在Alamofire4的请求体中添加或移除参数?
Hey there! I get exactly what you're trying to do—having a single, flexible parameter class that adapts to different API endpoints instead of creating a new one for every request makes total sense. Let's fix this properly, while also eliminating those JSON parsing errors you've been hitting.
The Core Issue
Your original RequestParameters class is hardcoded with specific properties, which makes it impossible to dynamically add/remove parameters. Plus, mixing Swift dictionaries with NSDictionary and forced downcasts can lead to JSON serialization failures (those parsing exceptions you mentioned).
Solution: A Flexible, Dynamic Parameter Builder
Let's rebuild RequestParameters to use a mutable Swift dictionary as its core, with built-in support for your common hotels parameter, plus methods to add/remove other parameters on the fly. We'll also ensure all parameters are JSON-serializable to avoid parsing errors.
Step 1: Refactor the Parameter Class
class RequestParameters: NSObject { // Use a Swift dictionary for better type safety and JSON compatibility private var parameters: [String: Any] = [:] // Initialize with the mandatory "hotels" parameter init(hotelParams: [String: Any]) { super.init() parameters["hotels"] = hotelParams } // Add a new parameter dynamically func addParameter(key: String, value: Any) { // Validate the value is JSON-serializable to avoid parsing issues guard JSONSerialization.isValidJSONObject(value) else { print("Warning: Value for key \(key) can't be serialized to JSON") return } parameters[key] = value } // Remove an existing parameter (blocks removal of mandatory "hotels") func removeParameter(key: String) { guard key != "hotels" else { print("Cannot remove mandatory 'hotels' parameter") return } parameters.removeValue(forKey: key) } // Return the final parameters for Alamofire func getParameters() -> [String: Any] { return parameters } }
Step 2: Update Custom Parameter Classes
Make sure your parameter classes return Swift dictionaries (not NSDictionary) from their params() method, and that all values are JSON-compatible:
class HotelParameter { func params() -> [String: Any] { // Return a JSON-friendly dictionary return ["hotelId": 456, "hotelName": "Ocean View Resort"] } } class FoodParameter { func params() -> [String: Any] { return ["category": "seafood", "isVegan": false] } } class AddressParameter { func params() -> [String: Any] { return ["street": "789 Coastal Rd", "city": "Miami"] } }
Step 3: Use the Dynamic Class in API Calls
Now you can easily adapt to different endpoints without creating new classes:
- First API (needs hotels, foodType, address):
let hotel = HotelParameter() let food = FoodParameter() let address = AddressParameter() // Initialize with mandatory hotels parameter let requestParams = RequestParameters(hotelParams: hotel.params()) // Add other required parameters requestParams.addParameter(key: "foodType", value: food.params()) requestParams.addParameter(key: "address", value: address.params()) // Execute Alamofire request Alamofire.request(url, method: .post, parameters: requestParams.getParameters(), encoding: JSONEncoding.default, headers: headers) .responseJSON { dataResponse in // Handle your response here }
- Second API (only needs hotels and address):
let hotel = HotelParameter() let address = AddressParameter() let requestParams = RequestParameters(hotelParams: hotel.params()) requestParams.addParameter(key: "address", value: address.params()) // No need to add foodType—just omit it! Alamofire.request(url, method: .post, parameters: requestParams.getParameters(), encoding: JSONEncoding.default, headers: headers) .responseJSON { dataResponse in // Handle your response here }
Why This Fixes JSON Parsing Errors
- Swift Native Types: We use
[String: Any]instead ofNSDictionaryand avoid forced downcasts (as! NSDictionary), which eliminates unexpected types that break JSON serialization. - Validation: The
addParametermethod checks if values are JSON-serializable before adding them, preventing invalid data from entering the request body. - No Hardcoding: The mutable dictionary lets you adapt to any endpoint's requirements without redundant class creation.
Bonus Enhancements (Optional)
- Add a method to check if a parameter exists:
func hasParameter(key: String) -> Bool - Make
hotelsoptional if some endpoints don't require it (adjust the init method accordingly) - Implement
Codableon your parameter classes for even safer, type-checked serialization
内容的提问来源于stack exchange,提问作者Bella

