【问题标题】:Extract value from dictionary of annoying format从烦人的格式字典中提取值
【发布时间】:2016-03-13 15:52:31
【问题描述】:

对于这个问题的标题,我深表歉意。我不知道还能叫什么。

所以...当调用以下命令时:

let testData: [NSObject : AnyObject] = getTestData() 
print(testData)

我得到这个输出:

[data: {"TypeId":7,"DataList":null,"TypeName":"This is a test"}]

如何访问键“TypeId”的值 7?

编辑: 请注意,它包含 { } 括号,而不仅仅是 [ ],因此就我所尝试的而言,无法转换为 NSDictionary。

亲切的问候, 安德斯

【问题讨论】:

  • 将字典中的数据解析为自定义对象。将数据保存为字典并不常见。
  • 是的,我非常愿意。但是这些数据来自服务器,所以我需要找到一种方法来读取它。

标签: ios arrays swift swift2 nsdictionary


【解决方案1】:

您可以使用 Any 类型的字典值实现类似 plist 的嵌套结构,这在某种程度上与 Objective-C 的 id 类型对应,但也可以保存值类型。

var response = Dictionary()

response["user"] = ["Login": "Power Ranger", "Password": "Mighty Morfin'"]

响应[“状态”] = 200

Any 似乎比 AnyObject 好,因为在上面的代码中 response["status"] 是 Swift.Int 类型,而使用 AnyObject 的值类型是 __NSCFNumber。

【讨论】:

  • 我看不出这是一个答案,请详细说明。
【解决方案2】:

大多数人的做法是将烦人的 JSON 数据解析为自定义对象。这应该在您获得 JSON 后立即完成。理想情况下,不应在通信代码之外使用 JSON 格式的数据,例如:

首先,让我们定义一个类来保存您的服务器数据:

class MyServerObject {
    let typeId: Int
    let typeName: String
    let dataList: [AnyObject]?

    init(dictionary: Dictionary<String, AnyObject>) {
        let dataDictionary = dictionary["data"] as! Dictionary<String, AnyObject>

        self.typeId = dataDictionary["TypeId"] as! Int
        self.typeName = dataDictionary["TypeName"] as! String
        self.dataList = dataDictionary["DataList"] as? [AnyObject]
    }
}

请注意,init 方法已经在解析 JSON。这不必在init 中完成,您也可以创建一个静态的parse 方法,该方法将返回一个新实例。

用法:

// demo data
let jsonString = "{\"data\": {\"TypeId\":7,\"DataList\":null,\"TypeName\":\"This is a test\"}}"
let jsonData = jsonString.dataUsingEncoding(NSUTF8StringEncoding)!
let json = try! NSJSONSerialization.JSONObjectWithData(jsonData, options: [])

// parsing
let myServerObject = MyServerObject(dictionary: json as! Dictionary<String, AnyObject>)

// now we can simply read data as properties
print(myServerObject.typeId)
print(myServerObject.typeName)

这个解决方案的一个好处是我们可以检查 JSON 格式并且所有属性都被解析为正确的类型。

解析可以是分层的,例如,如果你的dataList包含复杂的对象,我们称它们为DataListItem,你的解析方法可以单独解析每个项目并将它们放入[DataListItem],例如

if let dataListJSON = dataDictionary["DataList"] as? [Dictionary<String, AnyObject>] {
    self.dataList = dataListJSON.map({ DataListItem($0) })
}

还要注意,在解析as!时,格式无效时会导致应用崩溃。如果类型不匹配,as? 将返回 nilas? 对于可以是 nil 的类型非常有用,因为它们被解析为 NSNull 实例。

【讨论】:

    【解决方案3】:

    考虑您的数据...

    print(testData)
    /*
    [data: {
        DataList = null;
        TypeId = 7;
        TypeName = "This is a test";
     }]
     */
    
     // DataList type should be declared somewhere
     class DataList {}
    
     // parse data or set default value, if 'key' doesn't exist
     if let data = testData["data"] as? [String:AnyObject] {
    
         let dataList = data["DataList"] as? DataList        // nil
         let typeId = data["TypeId"] as? Int ?? 0            // 7
         let typeName = data["TypeName"] as? String ?? ""    // This is test
    
     }
    

    【讨论】:

    • 我没有通过你的保护。请注意,它包含 { } 括号,而不仅仅是 [ ]。
    • 如您所见,[] 和 {} 都是我的答案的一部分……那是您的情况,不是吗?
    • 让 data = testData["data"] as? [String:AnyObject] 在我的代码中返回 nil。
    • 请打印(testData) 并准确显示结果
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-04
    • 1970-01-01
    • 2018-02-02
    相关资源
    最近更新 更多