从字典键中提取值 - 然后组合成一个对象

Posted

技术标签:

【中文标题】从字典键中提取值 - 然后组合成一个对象【英文标题】:Extracting values from dictionary keys - then combining into an object 【发布时间】:2017-10-26 14:22:31 【问题描述】:

我有一个 JSON 响应,我已在 Swift 中将其解析为单个字典集 [String:Any]。我正在尝试检查每个键的值,然后将该值作为变量添加到 SteamFriend 对象的创建中。

for (key, value) in level3 
    var avatar:URL!
    var personaname:String = ""
    var personastate:Int = 0
    var steamid:String = ""

    if key == "avatar" 
        if let avatarAsString = value as? String 
            let avatarAsURL = URL(string: avatarAsString)
            avatar = avatarAsURL
        
     else if key == "personaname" 
        if let personanameAsString = value as? String 
            personaname = personanameAsString
        
     else if key == "personastate" 
        if let personastateAsInt = value as? Int 
            personastate = personastateAsInt
        
     else if key == "steamid" 
        if let steamidAsString = value as? String 
            steamid = steamidAsString
        
    

    let createSteamFriend = SteamFriend(avatar: avatar, personaname: 
    personaname, personastate: personastate, steamid: steamid)

SteamFriend 的类是

class SteamFriend 
var avatar: URL
var personaname: String
var personastate: Int
var steamid: String

init (avatar:URL, personaname:String, personastate: Int, steamid:String) 
    self.avatar = avatar
    self.personaname = personaname
    self.personastate = personastate
    self.steamid = steamid

当我运行上面的代码时,我立即在 createSteamFriend 行上收到一条错误消息,指出“在展开对象时意外发现 nil”。我已经针对上面的每个可选转换运行了一个打印语句,并且我知道它们都是返回值。

我确定我的代码逻辑存在缺陷。我一辈子都想不出创建 SteamFriend 对象的正确方法。

【问题讨论】:

let createSteamFriend = SteamFriend(...) 行放一个断点并检查值。另外,我认为您想在 for 循环之外(之后)执行该行,并将 var 声明也放在外面(在 for 循环之前)。还有SteamFriend(avatar:personaname:personastate: steamid:)的代码是什么? @larme 我现在将更新答案以包含 SteamFriend 类。 【参考方案1】:

问题是您在每个循环中重新声明变量,因此 URL 为 nil,除非在最后一次迭代中找到键 avatar

反正这是一种很麻烦的枚举字典的方式,直接获取key的值,不用循环:

var avatar: URL!

if let avatarAsString = level3["avatar"] as? String 
    let avatarAsURL = URL(string: avatarAsString)
    avatar = avatarAsURL

let personaname = level3["personaname"] as? String ?? ""
let personastate = level3["personastate"] as? Int ?? 0
let steamid = level3["steamid"] as? String ? ""

let createSteamFriend = SteamFriend(avatar: avatar, personaname: 
personaname, personastate: personastate, steamid: steamid)

如果初始化程序中的avatar 参数是必需的(非可选类型),我什至会写

guard let avatarAsString = level3["avatar"] as? String else  
  // show an error message
  return

let avatar = URL(string: avatarAsString)!

【讨论】:

谢谢老兄,就是这样。我做了太多的 for 循环。在你提到这个之后我立即在level3上做了一个打印,发现最后一个for循环是不必要的。【参考方案2】:

您正在为每个元素重置循环中的变量。 因此,一旦您找到“头像”,您就可以设置您的 URL。下一个元素,您将头像重置为 URL!。 把你的变量放在你的循环之外。

var avatar:URL!
var personaname:String = ""
var personastate:Int = 0
var steamid:String = ""

for (key, value) in level3 

if key == "avatar" 
    if let avatarAsString = value as? String 
        let avatarAsURL = URL(string: avatarAsString)
        avatar = avatarAsURL
    
 else if key == "personaname" 
    if let personanameAsString = value as? String 
        personaname = personanameAsString
    
 else if key == "personastate" 
    if let personastateAsInt = value as? Int 
        personastate = personastateAsInt
    
 else if key == "steamid" 
    if let steamidAsString = value as? String 
        steamid = steamidAsString
    



let createSteamFriend = SteamFriend(avatar: avatar, personaname: 
personaname, personastate: personastate, steamid: steamid)

【讨论】:

【参考方案3】:

基本上,您的 avatar 为 nil,因为您正在创建 createSteamFriend 实例四次,并且值一次单独出现。

如果你得到一个字典,为什么要运行循环?尝试直接从字典中获取值不要使用循环和不必要的 if else 条件。

var avatar = URL()

if let avatarAsString = level3["avatar"] as? String 
    let avatarAsURL = URL(string: avatarAsString)
    avatar = avatarAsURL

let personaname = level3["personaname"] as? String
let personastate = level3["personastate"] as? Int 
let steamid = level3["steamid"] as? String 

let createSteamFriend = SteamFriend(avatar: avatar, personaname: 
            personaname, personastate: personastate, steamid: steamid)

【讨论】:

以上是关于从字典键中提取值 - 然后组合成一个对象的主要内容,如果未能解决你的问题,请参考以下文章

Python:如何从字典键中随机选择一个值?

具有 Unity 和 Firebase 数据库的字典数组 - 从键中获取值

将多个数据文件组合成 np.arrays,存储在字典中

Zapier 编写的代码循环遍历一组对象,每个对象提取一个值,然后平均这些值

将 Json 对象存储在 Mongoose 字符串键中

将两个 Int32 组合成一个 Int64