Как использовать JSONDecoder с несколькими возможными структурами данных - PullRequest
1 голос
/ 16 мая 2019

Я анализирую поток данных JSON, представляющих события. В день, когда происходят события ARE, лента json будет Словарным словарём и будет выглядеть примерно так:

{
    "19374176" : 
    {
        "event_title" : "Cool Fun Thing to Do",
        "event_description" : "Have fun and do something cool",
        "event_start_time" : "13:00:00",
        "event_end_time" : "14:00:00"
    },
    "90485761634" :
    {
        "event_title" : "Nap Time",
        "event_description" : "Lay down and go to sleep.",
        "event_start_time" : "15:00:00",
        "event_end_time" : "16:00:00"
    }
}

У меня настроена структура, и я могу декодировать и использовать эту информацию так, как мне хотелось бы сейчас, с помощью этого кода, который является частью более крупной функции:

URLSession.shared.dataTask(with: url){(data, response, error) in
        if error != nil {
            print("session error: ", error!.localizedDescription)
        }

        guard let data = data else { return }

        do {
            let decoder = JSONDecoder()
            decoder.keyDecodingStrategy = .convertFromSnakeCase
            print(data)
            var eventData = try decoder.decode([String:Event].self, from: data)

            DispatchQueue.main.async{
                self.events = Array(eventData.values).sorted(by: {$0.timeStart < $1.timeStart
                })

                self.updateView()
                self.refreshControl.endRefreshing()
                self.activityIndicatorView.stopAnimating()
            }
        } catch DecodingError.typeMismatch(let type, let context){
            //No Dictionary of Events in Data
            print("key:", type, "context: ", context)
        } catch let jsonError{
            print("json error: ", jsonError)
        }
    }.resume()
}

Моя проблема сейчас заключается в том, что в дни, когда нет событий, фид json является пустым массивом:

[]

Это вызывает несовпадение типов, которое я обрабатываю, но если я пытаюсь вызвать функции updateView, refreshControl или activityIndicatorView из перехвата, я получаю ошибку, что не могу вызвать их вне основного потока.

Я пытался сделать вложенные блоки try, чтобы назначить переменную eventData (сначала чтобы узнать, является ли она [String] ((пустой массив, без событий)), а затем [String: Any] ((массив со значениями событий ))), но это дало мне ошибку для URLSession.

Есть ли лучший подход к этому, чтобы увидеть, является ли json пустым массивом по сравнению с заполненным словарем значений моего события, и обновить представления независимо от этого?

1 Ответ

3 голосов
/ 16 мая 2019

Попробуйте обновить их вне каких-либо блоков

do { 
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    print(data)
    var eventData = try decoder.decode([String:Event].self, from: data)
    self.events = Array(eventData.values).sorted(by: {$0.timeStart < $1.timeStart

} catch DecodingError.typeMismatch(let type, let context){
    //No Dictionary of Events in Data
    print("key:", type, "context: ", context)
} catch let jsonError{
    print("json error: ", jsonError)
}

DispatchQueue.main.async{
    self.updateView()
    self.refreshControl.endRefreshing()
    self.activityIndicatorView.stopAnimating()
}
...