2017-03-16 98 views
-3

我正在使用Swift 3中的iOS應用程序,並且調用服務器並返回json並將其序列化。在Swift 3中解析JSON時出錯

當我嘗試分析它,我得到這個錯誤:

"Could not cast value of type '__NSArrayI' (0x1a779acc8) to 'NSDictionary' (0x1a779b128). 2017-03-16 09:53:00.710776 AutoBuddy[3164:706970] Could not cast value of type '__NSArrayI' (0x1a779acc8) to 'NSDictionary' (0x1a779b128)."

我已經看到了這個問題的其他幾個版本,但我仍然感到困惑。從我所知道的情況來看,JSON可以作爲帶有鍵值對的字典返回[String:Any]。

我試着明確地調用了「as?Dictionary < String,Any>但是失敗的調用結果,這對我沒有意義,因爲我似乎正在獲取字典,但它不表現行爲作爲一個目前該程序崩潰在我的parseJSON函數的第一行我有一種感覺,問題是要麼我得到的JSON回來,或如何序列化它,因爲我已經使用過類似的解析方法之前和它總是工作或者如果它是一個分析問題,可能有人向我解釋,正確的方法來分析這一點,我會後的代碼,它序列化JSON的例子

JSON:?

["id": 745, "year": 1995, "styles": <__NSArrayI 0x170e68f00>(
{ 
    id = 7654; 
    name = "2dr Coupe"; 
    submodel =  { 
     body = Coupe; 
     modelName = "Mustang Coupe"; 
     niceName = coupe; 
    }; 
    trim = Base; 
}, 
{ 
    id = 7653; 
    name = "2dr Convertible"; 
    submodel =  { 
     body = Convertible; 
     modelName = "Mustang Convertible"; 
     niceName = convertible; 
    }; 
    trim = Base; 
}, 
{ 
    id = 7648; 
    name = "GT 2dr Coupe"; 
    submodel =  { 
     body = Coupe; 
     modelName = "Mustang Coupe"; 
     niceName = coupe; 
    }; 
    trim = GT; 
}, 
{ 
    id = 7647; 
    name = "GT 2dr Convertible"; 
    submodel =  { 
     body = Convertible; 
     modelName = "Mustang Convertible"; 
     niceName = convertible; 
    }; 
    trim = GT; 
}, 
{ 
    id = 7650; 
    name = "GTS 2dr Coupe"; 
    submodel =  { 
     body = Coupe; 
     modelName = "Mustang Coupe"; 
     niceName = coupe; 
    }; 
    trim = GTS; 
} 
) 
] 

Swift代碼:

func getJSONData(path: String) 
{ 
let config = URLSessionConfiguration.default 
    let session = URLSession(configuration: config) 
    let url = URL(string: path + "API key")! 

    let task = session.dataTask(with: url, completionHandler: 
     { 
      (data, response, error) in 
      if error != nil 
      { 
       print(error!.localizedDescription) 
      } 
      else 
      { 
       do { 
        if let resultJSON = try JSONSerialization.jsonObject(with: data!) as? [String: Any] 
        { 
         print(resultJSON) 
         self.parseJSON(json: resultJSON) 
        } 
       } 
       catch 
       { 
        print("\(error)") 
       } 
      } 
    }) 
    task.resume() 
} 
func parseJSON(json: [String: Any]) 
{ 
    let styles = json["styles"] as! [String:Any] // Crashes Here 
    print(styles) 
    let names = styles["name"] as! String 
    print(names) 
} 
+0

的[在夫特3正確地分析JSON]可能的複製(http://stackoverflow.com/questions/39423367/correctly-parsing-json-in-swift-3) – JAL

回答

0

我最終解決了這個問題,以防萬一任何人將此作爲參考。

func getJSONData(path: String) 
{ 
    let config = URLSessionConfiguration.default // Session Configuration 
    let session = URLSession(configuration: config) // Load configuration into Session 
    let url = URL(string: path + API_Key)! 

    let task = session.dataTask(with: url, completionHandler: 
     { 
      (data, response, error) in 
      if error != nil 
      { 
       print(error!.localizedDescription) 
      } 
      else 
      { 
       do { 
        let resultJSON = try JSONSerialization.jsonObject(with: data!) as! [String: Any] 
        let styles = resultJSON["styles"] as! NSArray 
        for i in 0..<styles.count 
        { 
         let name = styles[i] as! Dictionary<String, Any> 
         self.trims.append(name["name"] as! String) 
        } 
        DispatchQueue.main.async() { 
         self.tableView.reloadData() 
         self.tableView.isHidden = false 
         return 
        } 
       } 
       catch 
       { 
        print("Error: \(error)") 
       } 
      } 
    }) 
    task.resume() 
} 
3

請仔細閱讀JSON,這是非常容易的:

  • []表示一個數組中,斯威夫特[[String:Any]]或有時[Any]
  • {}代表一個字典,在Swift [String:Any]

styles的價值顯然是一個陣列(甚至明文指出:「風格」:< __NSArrayI 0x170e68f00>

let styles = json["styles"] as! [[String:Any]] 

,你需要一個重複循環,以獲得名

for style in styles { 
    let name = style["name"] as! String 
    print(name) 
} 

,或者您可以使用flatMap

let names = styles.flatMap { $0["name"] as? String } 
print(names) 

PS:在JSON的根對象似乎也是一個數組,如果是的話,你需要投

if let resultJSON = try JSONSerialization.jsonObject(with: data!) as? [[String: Any]] 

然後,你必須也改變

func parseJSON(json: [[String: Any]]) { 
    let styles = json[0]["styles"] as! [[String:Any]] 

避免方括號混淆我建議使用類型別名:

typealias JSONDictionary = [String:Any] 

然後一個字典是JSONDictionary,一個字典數組是[JSONDictionary],很容易區分。

+0

噢更有意義。我對事物的雙支撐部分感到困惑。我已經做了更改,並在行「let styles = json [」styles「] as![[String:Any]]」它給了我錯誤「不能下標值類型'[[String:Any]]'用'String'類型的索引。 我認爲這是因爲我傳遞的是「樣式」,當它是一個鍵/值對的數組時,它是一維的。有沒有辦法解決這個錯誤? – Jordan

+0

我更新了答案 – vadian

+0

我不知道這是不是很粗魯,但不應該是'[Any]'? – Desdenova