Анализ ответа ActionCable

#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
        ...
    }
}