#ios #json #swift #parsing #websocket
#iOS #json #swift #синтаксический анализ #websocket
Вопрос:
Я создаю приложение для iOS, в котором есть чаты. Он построен на ActionCable. Для работы с ним я использую библиотеку ActionCableClient. Все работает отлично. Единственная проблема с разбором полученного сообщения. Он имеет тип любой:
Optional({
data = {
author = {
"avatar_url" = "<null>";
name = "U0410U043bU043bU0430";
uid = "eb1b5fe6-5693-4966-bf72-a30596353677";
};
"created_at" = "1598446059.511528";
file = "<null>";
image = "<null>";
quote = "<null>";
status = red;
text = "test message";
type = OperatorMessage;
uid = "30b4d5ed-639d-46fb-9be3-b254de3b1203";
};
type = "operator_message";
})
И приведение любого типа к данным не работает. Я не могу повторно расшифровать это с помощью этого.
Я могу извлечь из него строку.
String(describing: data)
Но я больше не знаю, как его использовать. Как вы получаете из этого модель данных?
Комментарии:
1. Это словарь. Вы можете использовать это
as? [String: Any]
. Если вам нужен JSONDecoder из этого, вы можете преобразовать его обратно в данные, но, возможно, библиотека сможет его восстановить.
Ответ №1:
Это печать NSDictionary
. Итак, вы можете сделать:
guard let dict = that as? NSDictionary else { return }
или более быстрым способом:
guard let dict = that as? [String: Any] else { return }
И, например, получение некоторых значений:
let type = dict["type"] as? String
if let subdata = dict["data"] as? [String: Any] {
let text = subdata["text"] as? String
let kid = subdata["uid"] as? String
...
}
Если вы хотите получить (NS)Data
обратно, вы можете использовать JSONSerialization
для преобразования его обратно и использовать JSONDecoder
, но поскольку уже был
Data ----(through JSONSerialization)----> Dictionary
Возврат к данным означал бы
Data ----(through JSONSerialization)----> Dictionary ----(through JSONSerialization)----> Data ----(through JSONDecoder)----> CustomStruct
В то время как у вас может быть инициализация пользовательской структуры с вашим словарем.
Итак, если у вас есть кодируемая структура:
struct Response: Codable {
let data: CustomData
let type: String
}
struct CustomData: Codable {
let uid: String
let text: String
...
}
Самым быстрым способом было бы добавить:
extension Response {
init?(dict: [String;: Any] {
guard let type = dict["type"] as? String?
let data = dict["data"] as? [String: Any] else { return nil }
self.type = type
self.data = data
}
}
extension CustomData {
init?(dict: [String;: Any] {
guard let uid = dict["did"] as? String?
let text = dict["text"] as? String else { return nil }
self.uid = uid
self.text = text
...
}
}