Search code examples
swiftalamofirestrava

Parameters input from responseJSON to responseDecodable using Alamofire


I'm doing a .get request on Get Activity Streams (getActivityStreams) - Strava API using Alamofire.

I was using the .responseJSON method but since it will be deprecated in Alamofire 6 I am trying to switch to using the .responseDecodable however I am facing some issues. I have to inputs specific parameters in the request as an array of string

["keys": "latlng,time,altitude"]

This was my previous code that is functional

var headers : HTTPHeaders {
                  get {
                      return [
                          "Accept": "application/json",
                      ]
                  }
              }
    let url_activity = "https://www.strava.com/api/v3/activities/IDXXXX/streams"
    let params: [String: Any] =  [ "keys" : "latlng,time,altitude"]
    let head = HTTPHeaders(["Authorization" : "Bearer ACCESS_TOKEN"]) 
    AF.request(url_activity, method: .get, parameters: params, headers: head).responseJSON {
        response in
        switch response.result {
        case .success:
            print(response.value)
            break
        case .failure(let error):
            print(error)
        }
    }

I have declared a new struct and made it conform to the Encodable/Decodable protocol to handle these parameters and also used the encoder:JSONParameterEncoder.default in the request like in the example

struct DecodableType: Codable {
    let keys: [String: String]
}
let decode = DecodableType(keys: [ "keys" : ["latlng,time,altitude"]])

I have tried several versions like ["keys": "latlng,time,altitude"] or ["keys" : ["latlng","time","altitude"]] without any success, here is the new request :

        AF.request(url_act,
               method: .get,
               parameters: decode,
               encoder: JSONParameterEncoder.default ,
               headers: head).responseDecodable(of: DecodableType.self) {
        response in
        // Same as before

Here is the error code, I know it's related to 2019 Apple policy that making a GET request with body data will fail with an error but I can't find a solution

urlRequestValidationFailed(reason: Alamofire.AFError.URLRequestValidationFailureReason.bodyDataInGETRequest(33 bytes))

Thanks for you help !


Solution

  • I think you are mixing things up here. You are implementing Decodable and talking/naming it that way, but what you are doing is Encoding.

    It seems the Api expects a simple String as paramter, constructing it with a [String: String] seems ok. But what you are trying to send is JSON. I think the request is failing while trying to encode: ["keys": "latlng,time,altitude"] to your custom struct. Hence the error:

    urlRequestValidationFailed....bodyDataInGETRequest

    As has allready been pointed out in the comments you would need to use your old constructor for sending the request.

    AF.request(url_activity, method: .get, parameters: params, headers: head)
    

    then use the method:

    .responseDecodable(of: "what you expect in the response".self) {
    

    Here you need to provide a custom struct that conforms to Decodable and represents the >"returning json"<


    For the request you linked it would be:

    struct ResponseElement: Codable {
        let type: String
        let data: [Double]
        let seriesType: String
        let originalSize: Int
        let resolution: String
    
        enum CodingKeys: String, CodingKey {
            case type, data
            case seriesType = "series_type"
            case originalSize = "original_size"
            case resolution
        }
    }
    

    and decoding with:

    .responseDecodable(of: [ResponseElement].self) {