热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何在Swift中优雅地处理JSON【已翻译100%】

如何,在,swift,中,优雅,地处,理,jso

因为Swift对于类型有非常严格的控制,它在处理JSON时是挺麻烦的,因为它天生就是隐式类型。SwiftyJSON是一个能帮助我们在Swift中使用JSON的开源类库。开始之前,让我们先看一下在Swift中处理JSON是多么痛苦。

在Swift中使用JSON的问题

以Twitter API为例。使用Swift,从tweet中取得一个用户的“name”值应该非常简单。下面就是我们要处理的JSON:

[ { ...... "text": "just another test", ...... "user": { "name": "OAuth Dancer", "favourites_count": 7, "entities": { "url": { "urls": [ { "expanded_url": null, "url": "http://bit.ly/oauth-dancer", "indices": [ 0, 26 ], "display_url": null } ] } ...... }, "in_reply_to_screen_name": null, }, ......] 

在Swift中,你必须这样使用:

let jsonObject : AnyObject! = NSJSONSerialization.JSONObjectWithData(dataFromTwitter, options: NSJSONReadingOptions.MutableContainers, error: nil) if let statusesArray = jsonObject as? NSArray{ if let aStatus = statusesArray[0] as? NSDictionary{ if let user = aStatus["user"] as? NSDictionary{ if let userName = user["name"] as? NSDictionary{ //Finally We Got The Name } } } } 

或者,你可以用另外的一个方法,但这不易于阅读:

let jsonObject : AnyObject! = NSJSONSerialization.JSONObjectWithData(dataFromTwitter, options: NSJSONReadingOptions.MutableContainers, error: nil) if let userName = (((jsonObject as? NSArray)?[0] as? NSDictionary)?["user"] as? NSDictionary)?["name"]{ //What A disaster above } 

开始

下载在这儿下载SwiftyJSON,或者直接在GitHub克隆它:

git clone https://github.com/lingoer/SwiftyJSON.git 

基础用法

SwiftyJSON的使用十分的简单:

典型的NSURLSessionTask抓取Twitter的API将产生dataFromNetwork: NSData!:

你首先应该做的事情是初始化JSONValue:

let json = JSONValue(dataFromNetwork) 

JSONValue是一个枚举类型表示一个典型的JSON数据结构。

你能使用subscripts检索不同的值从原始的JSONValue中,像这样:

let userName:JSOnValue= json[0]["user"]["name"] 

注意userName仍然是一个JSONValue。那怎样得到一个字符串呢?
你能用.string属性得到JSON数据表示的真正值。

let userNameString = userName.string! 

对每一种JSON类型, JSONValue都提供了一种属性检索它:

var string: String? var number: NSNumber? var bool: Bool? var array: Array? var object: Dictionary? 

注意每一种属性都是一个Optional值。这是因为JSON数据能包含任何它定义的有效类型。
因此,建议的方式是用Optional绑定检索值:

if let name = userName.string{ //This could avoid lots of crashes caused by the unexpected data types } if let name = userName.number{ //As the value of the userName is Not a number. It won't execute. } 

.number属性产生一个NSNumber值,在Swift中这通常不是很有用。你能用.double或者.integer得到一个Double值或者一个Int值。

if let intValue = numberValue.integer{ count += intValue } 

枚举(Enumeration)
在Swift中JSONValue实际上是一个枚举:

enum JSONValue {

case JNumber(NSNumber) case JString(String) case JBool(Bool) case JNull case JArray(Array) case JObject(Dictionary) case JInvalid(NSError) 

}
你可以使用一个switch子句去更有效地获取值:

let json = JSONValue(jsonObject)
switch json["user_id"]{
case .JString(let stringValue):

let id = stringValue.toInt()

case .JNumber(let numberValue):

let id = numberValue.integerValue

default:

println("ooops!!! JSON Data is Unexpected or Broken")

下标(Subscripts)

注意,在JSON中一个数组结构被包装成intoArray,它意味着数组里的每一个元素都是一个JSONValue。甚至你从JSONValue中取出一个数组,你仍然可以使用基本的属性去获取元素的值:

if let array = json["key_of_array"].array{ if let string = array[0].string{ //The array[0] is still a JSONValue! } } 

对象也是一样。因此,推荐的方式是访问每一个数组和对象时使用JSONValue的下标。

if let string = json["key_of_array"][0].string{ } 

实际上,你可以用下标访问一个JSONValue,还不用担心运行时错误导致的崩溃:

let userName = json[99999]["wrong_key"] 

如果你使用推荐的方式去取数据,它是安全的:

if let userName = json[99999]["wrong_key"]["name"].string{ //It's always safe } 

打印

JSONValue遵守Printable协议.所以很容易在原始字符串中得到JSON数据:

let json = JSONValue(dataFromNetwork)
println(json)
/*You can get a well printed human readable raw JSON string:

 { "url": { "urls": [ { "expanded_url": null, "url": "http://bit.ly/oauth-dancer", "indices": [ 0, 26 ], "display_url": null } ] }

*/
如果你不想打印出来,你可以使用.description属性来得到上述字符串。

let printableString = json.description 

调试与错误处理

要是JSON数据出错或者我们错误地检索数据,那会怎么样呢?你可以使用if语句来测试:

let json = JSONValue(dataFromNetworking)["some_key"]["some_wrong_key"]["wrong_name"] if json{ //JSONValue it self conforms to Protocol "LogicValue", with JSONValue.JInvalid stands for false and others stands true } 

如果我们尝试使用错误的键值或索引来访问数据,description属性会高数你KeyPath在哪里出错了.

 let json = JSONValue(dataFromNetworking)["some_key"]["some_wrong_key"]["wrong_name"] if json{ } else { println(json) //> JSON Keypath Error: Incorrect Keypath "some_wrong_key/wrong_name" //It always tells you where your key went wrong switch json{ case .JInvalid(let error): //An NSError containing detailed error information } } 

后记

SwiftyJSON的开发将会发布在Github, 请持续关注后续版本。


推荐阅读
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • 本文介绍了GregorianCalendar类的基本信息,包括它是Calendar的子类,提供了世界上大多数国家使用的标准日历系统。默认情况下,它对应格里高利日历创立时的日期,但可以通过调用setGregorianChange()方法来更改起始日期。同时,文中还提到了GregorianCalendar类为每个日历字段使用的默认值。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
author-avatar
louis
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有