如何将 JSONDecoder 与多种可能的数据结构一起使用
How to use JSONDecoder with multiple possible data structures
我正在解析代表事件的 json 数据的提要。在有活动的一天,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: {[=11=].timeStart < .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 提要是一个空数组:
[]
这会导致我处理的类型不匹配,但是如果我尝试从 catch 调用 updateView、refreshControl 或 activityIndicatorView 的函数,我会收到一个错误,提示我无法在主线程外调用它们。
我尝试使用嵌套的 try 块来分配 eventData 变量(首先查看它是否为 [String]((空数组,无事件)),然后分配给 [String:Any]((具有值的数组事件))),但这给了我 URLSession 的错误。
是否有更好的方法来查看 json 是空数组还是我的事件值的填充字典并更新视图?
尝试在任何块之外刷新它们
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: {[=10=].timeStart < .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()
}
我正在解析代表事件的 json 数据的提要。在有活动的一天,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: {[=11=].timeStart < .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 提要是一个空数组:
[]
这会导致我处理的类型不匹配,但是如果我尝试从 catch 调用 updateView、refreshControl 或 activityIndicatorView 的函数,我会收到一个错误,提示我无法在主线程外调用它们。
我尝试使用嵌套的 try 块来分配 eventData 变量(首先查看它是否为 [String]((空数组,无事件)),然后分配给 [String:Any]((具有值的数组事件))),但这给了我 URLSession 的错误。
是否有更好的方法来查看 json 是空数组还是我的事件值的填充字典并更新视图?
尝试在任何块之外刷新它们
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: {[=10=].timeStart < .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()
}