解析json以允许字典的nil或默认值

时间:2016-08-17 20:37:07

标签: arrays json swift dictionary

我想我知道我的问题是什么,但我不知道如何解决它。我正在解析json,我知道我的变量“cooldown”偶尔会为零。返回nil时如何将值设置为0?这个问题出现在我的天才课上(也许不是正确的术语?)。我加粗了导致错误的代码。

错误是“致命错误:在解包可选值时意外发现nil”。

在执行“let talent = ...”之前,我尝试使用If语句来检查cooldown = nil但是这样做不起作用(或者我没有做对)。

if let talentsArray = dict[x]["talents"] as? Dictionary<String, AnyObject> {

                            for y in 0 ..< dict.count {
                                if let allHeroTalents = talentsArray["\(y)"]{
                                    for z in 0 ..< allHeroTalents.count {

                                        if let id = allHeroTalents[z]["id"], let name = allHeroTalents[z]["name"], let descritption = allHeroTalents[z]["description"], var cooldown = allHeroTalents[z]["cooldown"], let prerequisite = allHeroTalents[z]["prerequisite"], let icon = allHeroTalents[z]["icon"] {

                                            print("\(name) and \(cooldown)")

                                            let talent = Talent(id: id as! String, name: name as! String, description: description as! String, cooldown: cooldown as! Int, prerequisite: prerequisite as! String, icon: icon as! String)

                                        }
                                    }
                                }
                            }
                        }

让talent = Talent(id:id as!String,name:name as!String,description:description as!String,cooldown:cooldown as!Int,先决条件:先决条件为!String,icon:icon as !字符串)

我知道我告诉代码,因为“冷却时间:冷却时间为!Int”,冷却时间会有一个值,但是如果我拿出来的话!代码给了我另一个错误“可选类型Int not unwrapped的值”

我知道json正在工作,因为我添加了正确的打印

可选(加压压盖)和可选(6)

可选(生存本能)和零

可选(再生微生物)和可选(12)

可选(Envenomed Nest)和Optional(10)....

以下是供参考的课程

class Talent {
private var _id: String!
private var _name: String!
private var _description: String!
private var _cooldown: Int!
private var _prerequisite: String!
private var _icon: String!


var id: String {
    if _id == nil {
        _id = ""
    }
    return _id
}
var name: String {
    if _name == nil {
        _name = ""
    }
    return _name
}
var description: String {
    if _description == nil {
        _description = ""
    }
    return _description
}
var cooldown: Int {
    if _cooldown == nil {
        _cooldown = 0
    }
    return _cooldown
}


var prerequisite: String {
    if _prerequisite == nil {
        _prerequisite = ""
    }
    return _prerequisite
}
var icon: String {
    if _icon == nil {
        _icon = ""
    }
    return _icon
}

init(id: String, name: String, description: String, cooldown: Int, prerequisite: String, icon: String) {
    self._id = id
    self._name = name
    self._description = description
    self._cooldown = cooldown
    self._prerequisite = prerequisite
    self._icon = icon

}

}

根据要求添加相关的JSON(我认为这是你想要的)

func parseData(){
let urlString = "http://heroesjson.com/heroes.json"
let session = NSURLSession.sharedSession()
let url = NSURL(string: urlString)!
var stats = [Stats]()

session.dataTaskWithURL(url) { (data: NSData?, response:NSURLResponse?, error: NSError?) -> Void in

    if let responseData = data {

        do {
            let json = try NSJSONSerialization.JSONObjectWithData(responseData, options: NSJSONReadingOptions.AllowFragments)

            if let dict = json as? [Dictionary<String, AnyObject>] {

                for x in 0 ..< dict.count {


                    if let id = dict[x]["id"], let attributeid = dict[x]["attributeid"], let name = dict[x]["name"], let title = dict[x]["title"], let description = dict[x]["description"], let role = dict[x]["role"], let type = dict[x]["type"], let gender = dict[x]["gender"], let franchise = dict[x]["franchise"], let difficulty = dict[x]["difficulty"], let icon = dict[x]["icon"] {

                        let hero = Hero(id: id as! String, attributeid: attributeid as! String, name: name as! String, title: title as! String, description: description as! String, role: role as! String, type: type as! String, gender: gender as! String, franchise: franchise as! String, difficulty: difficulty as! String, icon: icon as! String)

                        if let dataArray = dict[x]["ratings"] as? Dictionary<String, Int> {

                            if let damage = dataArray["damage"], let utility = dataArray["utility"], let survivability = dataArray["damage"], let complexity = dataArray["complexity"] {

                                let rating = Ratings(damage: damage as! Int, utility: utility as! Int, survivability: survivability as! Int, complexity: complexity as! Int)
                                hero.ratings = rating

                            }
                        }

                        if let statsArray = dict[x]["stats"] as? Dictionary<String, AnyObject> {

                            let val = statsArray["talents"]

                            if let dummy = statsArray[hero.id]{//error handleing for vikings


                                if let hp = statsArray[hero.id]!["hp"], let hpPerLevel = statsArray[hero.id]!["hpPerLevel"], let hpRegen = statsArray[hero.id]!["hpRegen"], let hpRegenPerLevel = statsArray[hero.id]!["hpRegenPerLevel"], let mana = statsArray[hero.id]!["mana"], let manaPerLevel = statsArray[hero.id]!["manaPerLevel"], let manaRegen = statsArray[hero.id]!["manaRegen"], let manaRegenPerLevel = statsArray[hero.id]!["manaRegenPerLevel"] {


                                    let stats = Stats(hp: hp as! Int, hpPerLevel: hpPerLevel as! Int, hpRegen: hpRegen as! Float, hpRegenPerLevel: hpRegenPerLevel as! Float, mana: mana as! Int, manaPerLevel: manaPerLevel as! Int, manaRegen: manaRegen as! Float, manaRegenPerLevel: manaRegenPerLevel as! Float)

                                    hero.stats = stats
                                }
                            }
                        }
                        if let talentsArray = dict[x]["talents"] as? Dictionary<String, AnyObject> {

                            for y in 0 ..< dict.count {
                                if let allHeroTalents = talentsArray["\(y)"]{
                                    for z in 0 ..< allHeroTalents.count {


                                        if let id = allHeroTalents[z]["id"], let name = allHeroTalents[z]["name"], let descritption = allHeroTalents[z]["description"], var cooldown = allHeroTalents[z]["cooldown"], let prerequisite = allHeroTalents[z]["prerequisite"], let icon = allHeroTalents[z]["icon"] {

                                            print("\(name) and \(cooldown)")

                                            let talent = Talent(id: id as! String, name: name as! String, description: description as! String, cooldown: cooldown as! Int, prerequisite: prerequisite as! String, icon: icon as! String)

                                        }
                                    }
                                }
                            }






                        }


                        heroes.append(hero)
                    }
                }
            }
        } catch {
            print("Could not serialize")
        }
    }


    }.resume()

如果需要更多信息,请告诉我?

我非常擅长编码... 3周前开始所以如果标题不准确且我的代码效率低下,我道歉。

***这些是我根据人们的建议编辑的

我已经从if中取出了它并将其作为订单项

let id = allHeroTalents[z]["id"]
let name = allHeroTalents[z]["name"]
let description = allHeroTalents[z]["description"]
let cooldown = allHeroTalents[z]["cooldown"] ?? 0
let prerequisite = allHeroTalents[z]["prerequisite"] ?? ""
let icon = allHeroTalents[z]["icon"]



let sId = id as! String
let sName = name as! String
let sDescription = description as! String
let iCooldown = cooldown as! Int
let sPrerequisite = prerequisite as! String
let sIcon = icon as! String
let talent = Talent(id: sId, name: sName, description: sDescription, cooldown: iCooldown, prerequisite: sPrerequisite, icon: sIcon)

我的错误现在发生在“让sPrerequisite =先决条件为!字符串”

3 个答案:

答案 0 :(得分:1)

使用Swift&#34; Nil Coalescing Operator&#34; ??

var cooldown = allHeroTalents[z]["cooldown"] ?? 0

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html

上的Apple文档

答案 1 :(得分:0)

此解决方案假定nil是可接受的

Apple docs:

  

在可能缺席值的情况下使用选项

所以改变

private var _cooldown: Int!

private var _cooldown: Int?

在你的init(...)函数和你的Talent(...)构造函数调用中执行相同的操作:

cooldown: Int?
cooldown: cooldown as? Int

一些reading material为你

答案 2 :(得分:0)

处理像这样的代码中的问题时

let talent = Talent(id: id as! String, name: name as! String, description: description as! String, cooldown: cooldown as! Int, prerequisite: prerequisite as! String, icon: icon as! String)

推断错误的最简单方法是减少一行中发生的代码。做这件事:

let sId = id as! String
let sName = name as! String
let sDescription = description as! String
let iCooldown = cooldown as! Int
let sPrerequisite = prerequisite as! String
let sIcon = icon as! String
let talent = Talent(id: sId, name: sName, description: sDescription, cooldown: iCooldown, prerequisite: sPrerequisite, icon: sIcon)

现在你可以看到它们中的任何一个是否直接由引起错误的行引发错误。另外两个答案也是很好的信息。