#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() и укажите это в параметрах.