如何在swift 2中解析未知的json数据类型

时间:2016-03-06 19:57:59

标签: ios json xcode swift

从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 关键字以减少条件,但我不清楚如何在这里使用。

4 个答案:

答案 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)

您可以抓住您的回复课程。如果您的响应是类字典,如果您的响应是类数组,则将其指定为字典,将其分配给数组。祝你好运。