Swift原生JSON解析和第三方解析对比

来源:互联网 发布:超星阅览器 mac 编辑:程序博客网 时间:2024/05/21 00:52

如果 app 需要有网络功能并且有一个后端服务器处理和返回数据的话,那么现在基本上要和 JSON 打交道是没跑儿了的。在 Swift 里处理 JSON 其实是一件挺棘手的事情,因为 Swift 对于类型的要求非常严格,所以在解析完 JSON 之后想要从结果的 AnyObject 中获取某个键值是一件非常麻烦的事情。举个例子,我们使用 NSJSONSerialization 解析完一个 JSON 字符串后,得到的是 AnyObject?

// jsonString{"menu": {    "id": "file",    "value": "File",    "popup": {        "menuitem": [            {"value": "New", "onclick": "CreateNewDoc()"},            {"value": "Open", "onclick": "OpenDoc()"},            {"value": "Close", "onclick": "CloseDoc()"}        ]    }}}
let jsonString = //...let json: AnyObject = try! NSJSONSerialization.JSONObjectWithData(      jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!,    options: [])

我们如果想要访问 menu 里的 popup 中 第一个 menuitem 的 value 值的话,最正规的情况下,需要写这样的代码:

if let jsonDic = json as? NSDictionary {      if let menu = jsonDic["menu"] as? [String: AnyObject] {        if let popup: AnyObject = menu["popup"] {            if let popupDic = popup as? [String: AnyObject] {                if let menuItems: AnyObject = popupDic["menuitem"] {                    if let menuItemsArr = menuItems as? [AnyObject] {                        if let item0 = menuItemsArr[0]                                        as? [String: AnyObject] {                            if let value: AnyObject = item0["value"] {                                print(value)                            }                        }                    }                }            }        }    }}// 输出 New

什么?你难道把这段代码看完了?我都不忍心写下去了...如果你真的想要坚持这么做的话,我只能说呵呵,并且祝你好运了。

当然,在 Swift 1.2 中,我们可以在同一个 if let 语句中进行 unwrap,这样会比原来稍好一些,但是依旧十分麻烦:

if let jsonDic = json as? NSDictionary,            menu = jsonDic["menu"] as? [String: AnyObject],         popup = menu["popup"],      popupDic = popup as? [String: AnyObject],     menuItems = popupDic["menuitem"],  menuItemsArr = menuItems as? [AnyObject],         item0 = menuItemsArr[0] as? [String: AnyObject],         value = item0["value"]{    print(value)}

那么,我们应该怎么做呢?在上面的代码中,最大的问题在于我们为了保证类型的正确性,做了太多的转换和判断。我们并没有利用一个有效的 JSON 容器总应该是字典或者数组这个有用的特性,而导致每次使用下标取得的值都是需要转换的 AnyObject。如果我们能够重载下标的话,就可以通过下标的取值配合 Array 和 Dictionay 的 Optional Binding 来简单地在 JSON 中取值。鉴于篇幅,我们在这里不给出具体的实现。感兴趣的读者可以移步看看 json-swift 或者 SwiftyJSON 这样的项目,它就使用了重载下标访问的方式简化了 JSON 操作。使用这个工具,上面的访问可以简化为下面的类型安全的样子:

// 使用 SwiftJSONif let value = JSON(json)["menu"]["popup"]["menuitem"][0]["value"].string {      print(value)}

这样就简单多了。

0 0
原创粉丝点击