从api获取数据时,我可以得到响应产品数组或字典错误,例如
如果一切顺利,api会发送一系列产品:
[ "Product1": { name = "someting", price = 100, discount = 10%, images = [image1,image2] }, "Product2": { name = "someting", price = 100, discount = 10%, images = [image1,image2] } ]
但如果发生某些错误,它会发送包含错误消息和代码的字典:
{ error_message = "message" error_code = 202 }
我正在使用此代码将JSON数据转换为数组:
do {
let jsonDict = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSArray{
//Some code....
} catch let error as NSError {
print("JSON Error: \(error.localizedDescription)")
}
但是如果我收到错误的字典就崩溃了。
问题: 1.如何知道接收的数据是数组还是字典? 2.有时甚至键或值都可能丢失,因此检查值会变得非常冗长,例如:
if let productsArray = jsonObject as? NSArray{
if let product1 = productsArray[0] as? NSDictionary{
if let imagesArray = product1["image"] as? NSArray{
if let imageUrl = imagesArray[0] as? String{
//Code ....
}
}
}
}
我阅读了 guard 关键字以减少条件,但我不清楚如何在这里使用。
答案 0 :(得分:2)
问题1: 对于try catch,添加一个if let用于将对象转换为NSDictionary或NSArray,如:
do {
let jsonObject = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
if let jsonDict = jsonObject as? NSDictionary {
// Do smthg.
}
if let jsonArray = jsonObject as? NSArray {
// Do smthg.
}
}catch {
//...
}
对于问题2: 我认为后卫不会帮助你。它的else语句中需要像返回/中断一样的smthg。如果您的某个值不可用,那么如果您不想抛出您的方法,那么如果让代码样式,您必须使用这个冗长的方法。 也许在您的情况下,最佳实践是为具有可选属性的产品设置数据模型。
Class product {
var name:String?
var image:[NSData]? // maybe UIImage or smthg.
var price:Int?
var discount:Int?
init(jsonDic:NSDictionary){
// if it's not there it would be nil
self.name = jsonDic["name"] as? String
self.image = jsonDic["image"] as? NSArray
self.discount = jsonDic["discount"] as? Int
self.price = jsonDic["price"] as? Int
}
}
现在您可以使用您的数据加载这些模型而不使用if let等。 但是如果你想阅读这些值,你必须使用if let for checkin,如果它不是零。 对于你的情况下的init应该是这样的: 将其添加到do catch块的if let语句中(... as?NSArray // DO smthg。)
for item in jsonArray {
guard let jsonDic = item as? NSDictionary else { return }
// if you dont know every key you can just iterate through this dictionary
for (_,value) in jsonDic {
guard let jsonDicValues = value as? NSDictionary else { return }
productArray.append(Product(jsonDic: jsonDicValues)
}
}
正如我所说,知道如果从模型中读取而不是在写作时(阅读json),你会得到整体的东西
答案 1 :(得分:1)
这里有一些事情,一个,我会分析你的服务器的http响应状态代码,如果你收到一个状态代码表明你将拥有良好的数据,则只会尝试处理数据
// In practical scenarios, this may be a range
if statusCode != 200 {
// Handle a scenario where you don't have good data.
return
}
其次,我要防范这种反应,看起来你已经将它命名为#34;数据"像这样:
guard let receivedData = data else {
return
}
从现在开始,您可以使用receivedData常量。
这里' d我尝试使用NSJSONSeralization,就像你一样,但是把它放到Swift词典中,就像这样:
if let responseDictionary = try? NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? [String:AnyObject] {
// Here you can try to access keys on the response
// You can try things like
let products = responseDictionary?["products"] as? [[String:AnyObject]]
for product in products {
let productName = product["name"] as? String
if productName == nil {
continue
}
let newProduct = Product(name: productName)
// Do something with newly processed data
}
}
我试图做到一般,并向你展示一个守卫的例子。
答案 2 :(得分:1)
首先,我建议将SwiftyJSON pod或类直接用于您的Xcode,它的工作方式就像一个魅力,你不需要把事情弄清楚来判断你是否有字符串或字典管他呢。这是黄金。
一旦你获得了JSON,就可以使用我创建的这个递归函数来完成你所需要的。它将任何Json变成字典。我主要使用它将数据保存到Firebase中,而不必解析所有内容。
将SwiftyJSON导入项目并将SwiftyJSON导入Swift文件后,您可以:
let json = JSON(value) // Value is the json structure you received from API.
var myDictionary = [String:AnyObject]()
myDictionary = json2dic(json)
//JSON is created using the awesome SwiftyJSON pod
func json2dic(j: JSON) -> [String:AnyObject] {
var post = [String:AnyObject]()
for (key, object) in j {
post[key] = object.stringValue
if object.stringValue == "" {
post[key] = json2dic(object)
}
}
return post
}
答案 3 :(得分:0)
您可以抓住您的回复课程。如果您的响应是类字典,如果您的响应是类数组,则将其指定为字典,将其分配给数组。祝你好运。