Декодеры преобразуют данные в декодируемые значения.Они не имеют ничего общего с типами [String: Any]
или другими типами, не относящимися к данным.Поэтому, если вы хотите запустить его через декодер, вам нужно преобразовать его в JSON, закодированный в Data.
Если результаты [String: Any]
являются исключительно безопасными для JSONSerialization типами (массивы, словари, строки, числа, нуль)), тогда JSONSerialization.data(withJSONObject:options:)
позволит вам вернуться к данным, чтобы вы могли повторно декодировать их.Ваш код не просто перекодирует свои результаты, он сначала превращает его в массив:
let values = results.compactMap { $0.value }
let data = JSONSerialization.data (withJSONObject: values, options: [])
Это очень странно.Вы действительно хотите создать массив и выбросить ключи?Тогда я ожидал бы, что ваша строка JSONDecoder().decode()
будет декодировать [T].self
, а не T.self
.Поэтому я ожидаю следующий код (при условии, что ваш [String: Any]
является JSON-безопасным):
public func call<T: Decodable>(completion handler: @escaping (T?) -> ()) {
let promise = api.getPromise()
promise.done(on: .main) { (results: [String:Any]) in
guard JSONSerialization.isValidJSONObject(results) else {
handler(nil)
return
}
let data = JSONSerialization.data(withJSONObject: results)
let decodedResults = try? JSONDecoder().decode(T.self, from: data)
handler(decodedResults)
}
}
В комментариях вы заметите, что декодированные данные ([String: Any]
) не состоят из примитивов.В этом случае невозможно перекодировать его с помощью JSONSerialization.Вам нужно будет передать [String: Any]
кому-то, кто знает, как с этим справиться.Например:
protocol DictionaryDecodable {
init?(dictionary: [String: Any])
}
public func call<T: DictionaryDecodable>(completion handler: @escaping (T?) -> ()) {
let promise = api.getPromise ()
promise.done(on: .main) { (results: [String:Any])
handler(T.init(dictionary: results))
}
}
Вашим типам потребуется реализовать init?(dictionary:)
, который может декодировать свои собственные значения из [String: Any]
.