Запрос POST в формате JSON с Alamofire и EVReflection

#ios #json #swift

#iOS #json #swift

Вопрос:

Я пытаюсь выполнить простой POST-запрос в swift. Я хотел бы опубликовать массив объектов (аварийных сигналов), и я постоянно сталкиваюсь с проблемами. Вот что у меня есть до сих пор:

 func submitAlarms(alarms: [Alarm],onCompletion: @escaping ([Alarm]) -> Void){

    let route = baseURL

    let token = SessionManager().storedSession!.token.idToken

    let headers = [
        "Authorization": "Bearer (token)"
    ]


    let parameters = [
        "alarms": alarms.toJsonString()]

    print("Parameters ", parameters)


    Alamofire.request(route, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: headers)
        .validate()
        .responseJSON{ response in

            switch response.result{
            case .failure(let error):
                print("POST Alarm JSON Error: (error)")
            case .success(let value):
                let json = JSON(value)

                let alarms_json = json["alarms"]

                print(alarms_json)

                let alarms_string = alarms_json.rawString()

                let alarms: [Alarm] = [Alarm](json: alarms_string)

                //let alarms = [Alarm](json: res_string)

                onCompletion(alarms)

            }

    }

}
  

В основном у меня проблемы с parameters частью. По какой-то причине Alamofire, похоже, не может принимать массив объектов, поэтому я создал словарь с alarm ключом верхнего уровня, который содержит массив сигналов тревоги. Затем я использую EVReflection для преобразования моего массива сигналов тревоги в строку json. Но это обращение дает мне вот что:

 Parameters  ["alarms": "[n{n  "isActive" : true,n  "volume" : 10,n  "minute" : 15,n  "days" : [n    0,n    1,n    2,n    3,n    4,n    5,n    6n  ],n  "brightness" : 10,n  "hour" : 6,n  "audio" : 4,n  "duration" : 1,n  "label" : "Alarm",n  "allowSnooze" : false,n  "isSynchronized" : falsen}n]"]
  

Откуда все эти дополнительные и n исходящие? Используя Alamofire, сервер отвечает 400, потому что эти дополнительные фрагменты делают его недопустимым JSON. Что я здесь упускаю из виду? Я использую Xcode 8 / Swift 3 с последними версиями Alamofire и EVReflection. Я просмотрел другие примеры, но они в основном устарели. Многие из них также используют расширения и пользовательскую кодировку, что кажется смешным для такого простого запроса. Буду признателен за любую помощь и бонусные баллы, если вы также сможете очистить ответ.

Ответ №1:

Для создания параметров вы выполняете:

 let parameters = ["alarms": alarms.toJsonString()]
  

Это означает, что вы получите 1 параметр, который будет содержать json в виде строки.
EVReflection сначала преобразует объект alarms в словарь, а затем преобразует его в json с помощью стандартной функции Apple:

 JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
  

Поскольку он использует опцию .prettyPrinted, он будет отформатирован в удобном для чтения формате. Это означает, что он добавит /n для того, где должны быть вводы плюс пробелы для создания хорошего макета.

В вашем случае вам нужно посмотреть на api, который вы вызываете, чтобы увидеть, что вам следует изменить в своем коде. В настоящее время вы выполняете http get. Тогда параметры должны быть простыми парами ключ — значение. Для этого можно использовать функцию EVReflection ToDictionary, если вы хотите опубликовать все свои свойства объекта. Но в вашем случае, я думаю, вам нужно сделать post (см. Документацию Alamofire), а затем вы можете поместить json в тело запроса.

PS Я просто случайно обнаружил эту проблему. Вы также можете создавать проблемы на https://github.com/evermeer/EVReflection или задавайте вопросы по адресу https://gitter.im/evermeer/EVReflection Тогда я получу уведомление об этом.

Комментарии:

1. Да, я согласен, что моя проблема в том, что я создаю словарь с одним элементом и одной строкой json, тогда как то, что я действительно хочу, это полный словарь, включающий массив объектов alarm. Оттуда я считаю, что Alamofire правильно закодирует это в json. ToDictionary дал мне несколько действительно странных результатов, но я не потратил на это много времени. Кстати, я уже выполняю POST-запрос, см. Выше. Я проверю ссылку, спасибо

2. затем убедитесь, что вы не добавляете словарь в этот другой словарь. Просто выполните .ToDictionary() и укажите это в параметрах.