Запрос Moya Alamofire без кодировки URL

Как использовать get-API (со следующей структурой запроса) с Moya?

http://some.environment.com/some/api/some/contacts/81193?types=["details", "permissions"]

Вот что я пробовал.

enum MyApiTarget: TargetType {

    case getInfo(contactID: Int, types: [String])

    public var baseURL: URL {
        switch self {
        case .getInfo:
            return URL(string: "http://some.environment.com/some/api")!
        }
    }

    public var path: String {
        switch self {
        case .getInfo(contactID: let contactId, types: _):
            return "/some/contacts/\(contactId)"
        }
    }

    public var method: Moya.Method {
        switch self {
        case .getInfo:
            return .get
        }
    }

    public var sampleData: Data {
        return Data()
    }

    public var task: Task {
        switch self {
        case .getInfo(contactID: _, types: let types):
            return .requestParameters(
                 parameters: ["types" : types],
                 encoding: URLEncoding.queryString
            )
        }
    }

    public var headers: [String: String]? {
        return nil
    }

}

Приведенный выше код создает следующий URL-адрес.

http://some.environment.com/some/api/some/contacts/81193?types%5B%5D=details&types%5B%5D=permissions

Я пробовал следующие для кодирования

  • URLEncoding.queryString
  • URLEncoding.default
  • URLEncoding.httpBody
  • JSONEncoding.default
  • JSONEncoding.prettyPrinted

Ни одна кодировка не помогла мне добиться ожидаемого результата.


person Sagar R. Kothari    schedule 11.04.2018    source источник
comment
URL-адрес не может содержать скобки, это допустимо% 5B - '[' и% 5D - ']'   -  person Prashant Tukadiya    schedule 12.04.2018


Ответы (2)


Я решил это, добавив следующий код.

Замените задачу следующим образом.

public var task: Task {
    switch self {
        case .getInfo(contactID: _, types: let types):
            var arrayOfTypesInString = types.joined(separator: "\", \"")
            arrayOfTypesInString = "\"\(arrayOfTypesInString)\""
            let params = ["types": "[\(arrayOfTypesInString)]"]
            return .requestParameters(
                 parameters: params,
                 encoding: URLEncoding.queryString
            )
        }
    }
}

Пока что я сделал ручное JSON кодирование. Другой способ сделать это - сначала преобразовать данные в JSON и из JSON создать строку и предоставить.

person Sagar R. Kothari    schedule 16.04.2018

Я не знаю, как МОЯ

У меня была аналогичная проблема и аналогичная структура, что и у вас, и я исправил это с помощью

public protocol Router:URLRequestConvertible {
    var endPoint : String {get}
    var parameters:Parameters? {get}
    var httpMethod : HTTPMethod {get}
    var encoding:ParameterEncoding {get}
     func asURLRequest() throws -> URLRequest
}

Теперь у меня есть расширение, которое создает URL-адрес из всех включенных свойств протокола encoding:ParameterEncoding

extension Router {
    func asURLRequest() throws -> URLRequest {

        // Generate URL
        let url = try Constants.APIConstants.BaseURL.production.rawValue.asURL()

        // Generate  URL Request
        var urlRequest = URLRequest(url: url.appendingPathComponent(endPoint))

        // Generate Headers

        urlRequest.addValue("application/json", forHTTPHeaderField:"Content-Type")
        urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
        urlRequest.addValue(Constants.APIConstants.RequestKeys.APIKEY_Val, forHTTPHeaderField:  Constants.APIConstants.RequestKeys.APIKEY)
        urlRequest.addValue(Constants.APIConstants.RequestKeys.APIVERSION_Val , forHTTPHeaderField:Constants.APIConstants.RequestKeys.APIVERSION )
        urlRequest.addValue(authToken, forHTTPHeaderField:Constants.APIConstants.RequestKeys.AUTHTOKEN )

        urlRequest.httpMethod = self.httpMethod.rawValue


        if let parameters = parameters {
            do {
                urlRequest.httpBody = try JSONSerialization.data(withJSONObject: parameters, options:[])
                urlRequest =  try  self.encoding.encode(urlRequest, with: parameters)

            } catch {
                throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
            }
        }

        return urlRequest

    }
}

Теперь у меня есть перечисление

enum APIRouterUserModule : Router {

    case login(email:String,password:String) 

     // Implement all the  Router protocol property (similar to your strct.) here is example for encoding 

            var encoding: ParameterEncoding {
                 switch self {
                     case .login :
                     return URLEncoding.queryString
                    //Return any of them 
                        /*
                   URLEncoding.queryString
                   URLEncoding.default
                   URLEncoding.httpBody
                   JSONEncoding.default
                   JSONEncoding.prettyPrinted */
                  }

             }
   }

Надеюсь, это будет полезно

person Prashant Tukadiya    schedule 11.04.2018
comment
Спасибо за ответ, но это характерно для Moya с Alamofire. - person Sagar R. Kothari; 12.04.2018