簡體   English   中英

如何在swift 2中解析未知的json數據類型

[英]How to parse unknown json data type in swift 2

從 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關鍵字以減少if 條件的信息,但我不清楚如何在此處使用。

問題 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:我認為 guard 不會幫助你。 它在 else 語句中需要像 return / break 這樣的 smthg。 如果您不想在您的值之一不可用時拋出您的方法,您必須使用這個冗長的 if let 代碼樣式。 也許在您的情況下,最佳實踐是為具有可選屬性的產品設置數據模型。

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 進行檢查,如果它不是 nil。 對於 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 ),你就知道了

你在這里有幾件事要做,一,我會分析你的服務器的 http 響應狀態代碼,只有當你收到一個狀態代碼時才嘗試處理數據,表明你會有好的數據

// In practical scenarios, this may be a range
if statusCode != 200 {
// Handle a scenario where you don't have good data.
return
}

其次,我會防范響應,看起來您已將其命名為“數據”,如下所示:

guard let receivedData = data else {
return 
}

從現在開始,您可以使用 receivedData 常量。

在這里,我會嘗試像您一樣使用 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

 } 

}

我試圖成為一般人,並向你展示了一個守衛的例子。

首先,我建議將SwiftyJSON pod 或類直接使用到您的 Xcode 中,它的作用就像一個魅力,您無需將事情分解來確定您是否有字符串或字典或其他任何東西。 它是黃金。

獲得 JSON 后,您可以使用我創建的這個遞歸函數,它完全符合您的需要。 它將任何 Json 變成字典。 我主要使用它來將數據保存到 Firebase 中,而無需解析所有內容。

將 SwiftyJSON 導入項目並將 import SwiftyJSON 添加到 Swift 文件后,您可以:

    //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 as AnyObject
            if object.stringValue == "" {
                post[key] = json2dic(object) as AnyObject
            }
        }
        return post
    }


    let json = JSON(value) // Value is the json structure you received from API.
    var myDictionary = [String:AnyObject]()
    myDictionary = json2dic(json)

你可以抓住你的回應的類別。 如果您的響應是類字典,則將其分配為字典;如果您的響應是類數組,則將其分配給數組。 祝你好運。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM