2017-02-11 91 views
0

我从一个生成json数组的php脚本中提取数据。 iOS更新后,我的jsonserialization崩溃了应用程序。根据jsonformatter.org和freeformatter.com/json-validator.html(符合RFC4627),json应该很好地形成。 这是代码。任何帮助是极大的赞赏!JSON序列化错误

func parseJSON() { 

    var jsonResult: NSMutableArray = NSMutableArray() 

    do{ 
     jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray 

    } catch let error as NSError { 
     print(error) 

    } 

    var jsonElement: NSDictionary = NSDictionary() 
    let locations: NSMutableArray = NSMutableArray() 

    for i in 0 ..< jsonResult.count 
    { 

     jsonElement = jsonResult[i] as! NSDictionary 

     let location = LocationModel() 

     //the following insures none of the JsonElement values are nil through optional binding 
     if let id = jsonElement["id"] as? String, 
      let oprettelsesdato = jsonElement["oprettelsesdato"] as? String, 
      let overskrift = jsonElement["overskrift"] as? String, 
      let address = jsonElement["address"] as? String, 
      let intro = jsonElement["intro"] as? String, 
      let email = jsonElement["email"] as? String, 
      let tlf = jsonElement["tlf"] as? String, 
      let annonce = jsonElement["annonce"] as? String, 
      let journalnr = jsonElement["journal"] as? String 
     { 

      location.id = id 
      location.oprettelsesdato = oprettelsesdato 
      location.overskrift = overskrift 
      location.address = address 
      location.intro = intro 
      location.email = email 
      location.tlf = tlf 
      location.annonce = annonce 
      location.journalnr = journalnr 


     } 

     locations.add(location) 

    } 

    DispatchQueue.main.async(execute: {() -> Void in 
     //print("Check home") 
     self.delegate.itemsDownloaded(locations) 

    }) 
} 

系统崩溃日志:

objc[1285]: Class PLBuildVersion is implemented in both /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/AssetsLibraryServices.framework/AssetsLibraryServices (0x11799a998) and /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/PhotoLibraryServices.framework/PhotoLibraryServices (0x1177bc880). One of the two will be used. Which one is undefined. 
Could not cast value of type '__NSArrayI' (0x105f1ed88) to 'NSMutableArray' (0x105f1ee50). 

UPDATE 我现在用vadians解决方案,但是,而不是self.delegate.itemsDownloaded(位置),我用self.delegate.itemsDownloaded(如位置NSArray的)。

但是,所有jsonElements现在都是零。它得到数组中元素的正确数目,但如果我打印的所有值均为零:

(
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil", 
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil" 
) 

这里是我尝试恢复数据。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

    let item: LocationModel = feedItems[indexPath.row] as! LocationModel 
    let cellIdentifier: String = "BasicCell" 
    let myCell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)! 



    //myCell.detailTextLabel!.text = item.oprettelsesdato 
    myCell.textLabel!.text = item.overskrift 
    myCell.textLabel!.leadingAnchor.constraint(equalTo: myCell.leadingAnchor).isActive = true 
    myCell.textLabel!.topAnchor.constraint(equalTo: myCell.topAnchor).isActive = true 
    myCell.textLabel!.heightAnchor.constraint(equalTo: myCell.heightAnchor, 
               multiplier: 1.0).isActive = true 
    myCell.textLabel!.widthAnchor.constraint(equalTo: myCell.heightAnchor, 
               multiplier: 0.8).isActive = true 


    //print(item.id) <-returns nil 
    //print(item.oprettelsesdato) <-returns nil 
    //print(item.overskrift) <-returns nil 
    extralabel!.text = item.oprettelsesdato // <-This is where the error is thrown 
    extralabel!.textColor = UIColor.white 
    myCell.contentView.addSubview(extralabel!) 

//some more stuff... 
} 

错误:

fatal error: unexpectedly found nil while unwrapping an Optional value 

不知道什么错误。有什么建议么?

+2

你可以显示你的崩溃日志吗? –

+0

jsonResult =尝试JSONSerialization.jsonObject(使用:self.data作为数据,选项:JSONSerialization.ReadingOptions.allowFragments)as! NSMutableArray将此行更改为jsonResult = try JSONSerialization.jsonObject(with:self.data as Data,options:JSONSerialization.ReadingOptions.allowFragments)as? NSMutableArray将工作 –

+2

简单的建议。 **不要 - 永远不要在Swift中使用'NSMutable ...'集合类型**。它们与Swift收集类型无关并导致您的所有问题。 – vadian

回答

1

什么是你的问题的关键是这一部分as! NSMutableArray在该行:

jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray 

即使在较老的iOS的,转换的NSJSONSerialization.JSONObjectWithDataNSMutableArray结果不保证操作(当你不指定.mutableContainers选项)。

看到你的整个代码,你是不是变异jsonResult,这样你就可以用一个简单的NSArray而不是NSMutableArray

var jsonResult: NSArray = NSArray() 

    do{ 
     jsonResult = try JSONSerialization.jsonObject(with: self.data as Data) as! NSArray 

    } catch let error as NSError { 
     print(error) 

    } 

我建议你使用斯威夫特类型,如DataArrayDictionary,而不是NSDataNSArrayNSMutableArray)或NSDictionary。但这对你的情况并不重要。

+0

谢谢。这点解决了这个错误。我认为我在json数组中有一个空元素,我认为这会导致更多的错误。 json数组非常大,所以不容易检查。但感谢您的帮助! – user1378824

+0

@ user1378824,我明白了。希望你能尽快解决你的问题,或者我们可以帮助你解决你的问题。 – OOPer

3

请让我重复我的评论:

不 - 从来没有 - 斯威夫特用NSMutable...集合类型。

它们与Swift集合类型无关并导致所有问题。 var关键字使得任何Swift对象都是可变的,非常容易使用。除此之外,收到的数组在您的代码中完全没有发生变异。

不幸的半知识教程这表明NSMutable...永远不会死关:/

在夫特3

  • 一个JSON字典是[String:Any]
  • JSON数组是[[String:Any]][Any]

由于JSON对象应该是一个数组.allowframents是相当无用的。

所以:

func parseJSON() { 

    var jsonResult = [[String:Any]]() 

    do{ 
     jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:[]) as! [[String:Any]] 

    } catch { 
     print(error) 
     return 
    } 

    var locations = [LocationModel]() 

    for jsonElement in jsonResult { // no ugly C-style index based loops! 

     let location = LocationModel() 

     //the following insures none of the JsonElement values are nil through optional binding 
     if let id = jsonElement["id"] as? String, 
      let oprettelsesdato = jsonElement["oprettelsesdato"] as? String, 
      let overskrift = jsonElement["overskrift"] as? String, 
      let address = jsonElement["address"] as? String, 
      let intro = jsonElement["intro"] as? String, 
      let email = jsonElement["email"] as? String, 
      let tlf = jsonElement["tlf"] as? String, 
      let annonce = jsonElement["annonce"] as? String, 
      let journalnr = jsonElement["journal"] as? String 
     { 

      location.id = id 
      location.oprettelsesdato = oprettelsesdato 
      location.overskrift = overskrift 
      location.address = address 
      location.intro = intro 
      location.email = email 
      location.tlf = tlf 
      location.annonce = annonce 
      location.journalnr = journalnr 


     } 

     locations.append(location) 

    } 

    DispatchQueue.main.async { 
     //print("Check home") 
     self.delegate.itemsDownloaded(locations) 
    } 
} 

注意:如果jsonElement只包含字符串,你甚至可以投的字典[String:String],摆脱所有as? String转换。

2

我建议创建一个可选的init方法,它需要json并尝试创建一个LocationModel

struct LocationModel { 

    var id: String 
    var oprettelsesdato: String 
    var overskrift: String 
    var address: String 
    var intro: String 
    var email: String 
    var tlf: String 
    var annonce: String 
    var journalnr: String 

    init?(json: [String:Any]) { 

     guard 
      let id = json["id"] as? String, 
      let oprettelsesdato = json["oprettelsesdato"] as? String, 
      let overskrift = json["overskrift"] as? String, 
      let address = json["address"] as? String, 
      let intro = json["intro"] as? String, 
      let email = json["email"] as? String, 
      let tlf = json["tlf"] as? String, 
      let annonce = json["annonce"] as? String, 
      let journalnr = json["journal"] as? String else { return } 

     self.id = id 
     self.oprettelsesdato = oprettelsesdato 
     self.overskrift = overskrift 
     self.address = address 
     self.intro = intro 
     self.email = email 
     self.tlf = tlf 
     self.annonce = annonce 
     self.journalnr = journalnr 
    } 
} 

然后,在parseJSON功能,而不是使用NSMutableArray,您可以使用[LocationModel]。这样我们可以直接使用json.flatMap { LocationModel(json: $0) }来使用json元素([[String:Any]])到[LocationModel]的数组flatMap

func parseJSON() { 

    var locations = [LocationModel]() 

    do{ 
     if let json = try JSONSerialization.jsonObject(with: data as Data, options: []) as? [[String:Any]] { 
      locations = json.flatMap { LocationModel(json: $0) } 
     } 
    } catch let error as NSError { 
     print(error) 
    } 

    DispatchQueue.main.async { 
     self.delegate.itemsDownloaded(locations) 
    } 
}