TL;DR - the API cannot be changed, and the variable parameters are a vital part of my app.
I've created a type that stores parameters for an API call.
To make use of them with a successful request, I first need to format them into the URL.
Say, my parameters are expressed as such:
struct Parameters: Encodable {
var name: String
var taste: Taste
var numberOfSpoons: Int?
var topping: Taste?
private enum CodingKeys: String, CodingKey {
case name, taste, topping
case numberOfSpoons = "spoons"
}
init(name: String, taste: Taste, numberOfSpoons: Int? = 1, topping: Taste? = nil){
self.name = name
self.taste = taste
self.numberOfSpoons = numberOfSpoons
self.topping = topping
}
}
Notice that my structure uses both Optionals (as the API does not need all the parameters from my app) and CodingKeys (as the names requested by the API look rather ugly in the code, but are necessary).
Here's the Taste - not much going on except explicit Encodable conformance.
enum Taste: String, Encodable {
case choco, strawberry, vanilla
}
Now I want to call the API, so, according to the suggestion of John Sundell (I can't provide a link to the article due to Apple's censorship), I'm using URLComponents. For example:
var components = URLComponents()
components.scheme = "ftp"
components.host = "icecream.ogs"
components.path = "/spoons"
If I were to add queryItems by hand, it would be fairly easy.
components.queryItems = [
URLQueryItem(name: "name", value: iceCreamParameters.name),
URLQueryItem(name: "numberOfSpoons", value: "\(iceCreamParameters.numberOfSpoons!)")
]
How to dynamically create URLQueryItems from a non-CaseIterable type?
The URLQueryItem needs both name and value parameters. I want the i-th name to be equal to I-thParameters.PropertyName, the same goes for values.
As CaseIterable would not be feasible to implement* in the Parameters struct, I tried to fake it using the Encodable protocol - I thought about serializing the type to JSON (as the encoder gets rid of nil values, too) and then somehow get the keys from a deserialized Dictionary of AnyType (?), but there's got to be a better way.
If this approach is not feasible, please provide your answers with helpful examples.