如何在 Swift 中优雅地处理 JSON
阅读目录
因为Swift对于类型有非常严格的控制,它在处理JSON时是挺麻烦的,因为它天生就是隐式类型。SwiftyJSON是一个能帮助我们在Swift中使用JSON的开源类库。开始之前,让我们先看一下在Swift中处理JSON是多么痛苦。
在Swift中使用JSON的问题
以Twitter API为例。使用Swift,从tweet中取得一个用户的“name”值应该非常简单。下面就是我们要处理的JSON:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
[ { ...... "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中,你必须这样使用:
|
1
2
3
4
5
6
7
8
9
10
11
|
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 } } }} |
或者,你可以用另外的一个方法,但这不易于阅读:
|
1
2
3
4
|
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克隆它:
|
1
|
git clone https://github.com/lingoer/SwiftyJSON.git |
基础用法
SwiftyJSON的使用十分的简单:
典型的NSURLSessionTask抓取Twitter的API将产生dataFromNetwork: NSData!:
你首先应该做的事情是初始化JSONValue:
|
1
|
let json = JSONValue(dataFromNetwork) |
JSONValue是一个枚举类型表示一个典型的JSON数据结构。
你能使用subscripts检索不同的值从原始的JSONValue中,像这样:
|
1
|
let userName:JSONValue = json[0]["user"]["name"] |
注意userName仍然是一个JSONValue。那怎样得到一个字符串呢?
你能用.string属性得到JSON数据表示的真正值。
|
1
|
let userNameString = userName.string! |
对每一种JSON类型, JSONValue都提供了一种属性检索它:
|
1
2
3
4
5
|
var string: String?var number: NSNumber?var bool: Bool? var array: Array<JSONValue>?var object: Dictionary<String, JSONValue>? |
注意每一种属性都是一个Optional值。这是因为JSON数据能包含任何它定义的有效类型。
因此,建议的方式是用Optional绑定检索值:
|
1
2
3
4
5
6
7
|
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值。
|
1
2
3
|
if let intValue = numberValue.integer{ count += intValue} |
枚举(Enumeration)
在Swift中JSONValue实际上是一个枚举:
|
1
2
3
4
5
6
7
8
9
10
11
|
enum JSONValue { case JNumber(NSNumber) case JString(String) case JBool(Bool) case JNull case JArray(Array<JSONValue>) case JObject(Dictionary<String,JSONValue>) case JInvalid(NSError)} |
你可以使用一个switch子句去更有效地获取值:
|
1
2
3
4
5
6
7
8
|
let json = JSONValue(jsonObject)switch json["user_id"]{case .JString(let stringValue): let id = stringValue.toInt()case .JNumber(let numberValue): let id = numberValue.integerValuedefault: println("ooops!!! JSON Data is Unexpected or Broken") |
下标(Subscripts)
注意,在JSON中一个数组结构被包装成intoArray<JSONVlaue>,它意味着数组里的每一个元素都是一个JSONValue。甚至你从JSONValue中取出一个数组,你仍然可以使用基本的属性去获取元素的值:
|
1
2
3
4
5
|
if let array = json["key_of_array"].array{ if let string = array[0].string{ //The array[0] is still a JSONValue! }} |
对象也是一样。因此,推荐的方式是访问每一个数组和对象时使用JSONValue的下标。
|
1
2
3
|
if let string = json["key_of_array"][0].string{} |
实际上,你可以用下标访问一个JSONValue,还不用担心运行时错误导致的崩溃:
|
1
|
let userName = json[99999]["wrong_key"] |
如果你使用推荐的方式去取数据,它是安全的:
|
1
2
3
|
if let userName = json[99999]["wrong_key"]["name"].string{ //It's always safe} |
打印
JSONValue遵守Printable协议.所以很容易在原始字符串中得到JSON数据:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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属性来得到上述字符串。
|
1
|
let printableString = json.description |
调试与错误处理
要是JSON数据出错或者我们错误地检索数据,那会怎么样呢?你可以使用if语句来测试:
|
1
2
3
4
|
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在哪里出错了.
|
1
2
3
4
5
6
7
8
9
10
11
12
|
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, 请持续关注后续版本。
本文地址:http://www.oschina.net/translate/swiftyjson-how-to-handle-json-in-swift
原文地址:http://www.binpress.com/tutorial/swiftyjson-how-to-handle-json-in-swift/111
如何在 Swift 中优雅地处理 JSON的更多相关文章
- 阿里巴巴最新开源项目 - [HandyJSON] 在Swift中优雅地处理JSON
项目名称:HandyJSON 项目地址:https://github.com/alibaba/handyjson 背景 JSON是移动端开发常用的应用层数据交换协议.最常见的场景便是,客户端向服务端发 ...
- 如何在MyBatis中优雅的使用枚举
问题 在编码过程中,经常会遇到用某个数值来表示某种状态.类型或者阶段的情况,比如有这样一个枚举: public enum ComputerState { OPEN(10), //开启 CLOSE( ...
- 如何在 Swoole 中优雅的实现 MySQL 连接池
如何在 Swoole 中优雅的实现 MySQL 连接池 一.为什么需要连接池 ? 数据库连接池指的是程序和数据库之间保持一定数量的连接不断开, 并且各个请求的连接可以相互复用, 减少重复连接数据库带来 ...
- 如何在swift中实现oc中的分类
在oc中为了增强已有类的功能,我们经常使用分类.使用分类,我们可以在不破坏原有类的结构的前提下,对原有类进行模块化的扩展. 但是在swift中没有分类这种写法了.相对应的是swift中只有扩展(Ext ...
- iOS: 在Swift中优雅的实现Substring
在Swift中,当我们想要截取某个字符串时,方法如下: let carNumber = "沪A12345" let startIndex = advance(userCar.car ...
- 如何在Vue中优雅的使用防抖节流
1. 什么是防抖节流 防抖:防止重复点击触发事件 首先啥是抖? 抖就是一哆嗦!原本点一下,现在点了3下!不知道老铁脑子是不是很有画面感!哈哈哈哈哈哈 典型应用就是防止用户多次重复点击请求数据. 代码实 ...
- 如何在K8S中优雅的使用私有镜像库 (Docker版)
前言 在企业落地 K8S 的过程中,私有镜像库 (专用镜像库) 必不可少,特别是在 Docker Hub 开始对免费用户限流之后, 越发的体现了搭建私有镜像库的重要性. 私有镜像库不但可以加速镜像的拉 ...
- IOS开发问题录:如何在Swift中引入Head文件?
最近在学习IOS开发,从一个简单的登录开始,逐步解决了一个网络访问.获取控件值等问题,遇到了信息加密的问题. 做为IOS的入门者,信息加密需要解决如下几个问题: 1.IOS的MD5加密有没有固定函数, ...
- 如何在php中优雅的地调用python程序
1.准备工作 安装有python和php环境的电脑一台. 2.书写程序. php程序如下 我们也可以将exec('python test.py') 换成 system('python test.p ...
随机推荐
- 什么是Spring?Spring是什么?
Spring概述: Spring是一个开源框架,是为了解决企业应用程序开发复杂性而开发的. 从简单性.可測试性和松耦合的角度而言,不论什么java应用都能够从Spring中受益. 简而言之,Sprin ...
- Groovy常见语法汇总
一.groovy是什么 简单地说,Groovy 是下一代的java语言,跟java一样,它也运行在 JVM 中. 作为跑在JVM中的另一种语言,groovy语法与 Java 语言的语法很相似.同时,G ...
- 怎样改动SVN的地址
改动svn地址的目的有两个,一个是更改默认svn路径.还有一个就是svn库server迁移了. 我碰到的是另外一种情况,SVN的IP地址改了,须要这么切换: 在本地配置库副本根文件夹点击鼠标右键--& ...
- URAL 1297 后缀数组:求最长回文子串
思路:这题下午搞了然后一直WA,后面就看了Discuss,里面有个数组:ABCDEFDCBA,这个我输出ABCD,所以错了. 然后才知道自己写的后缀数组对这个回文子串有bug,然后就不知道怎么改了. ...
- TCP/IP协议栈源码图解分析系列10:linux内核协议栈中对于socket相关API的实现
题记:本系列文章的目的是抛开书本从Linux内核源代码的角度详细分析TCP/IP协议栈内核相关技术 轻松搞定TCP/IP协议栈,原创文章欢迎交流, byhankswang@gmail.com linu ...
- 使用windows-SQLyog连接linux-mysql
嘿嘿,最近又清闲了一点,重新安装了mysql去学习. -----博客园-邦邦酱好 系统环境: 1. 主机为windows系统,安装了SQLyog. 2. 主机上还安装了虚拟机,系统为c ...
- 在Xshell中上传下载文件到本地(linux中从多次ssh登录的dbserver里面的文件夹)
在Xshell中上传下载文件到本地(linux中从多次ssh登录的dbserver里面的文件夹) 1 列出所有需要copy的sh文件 -bash-4.1$ ll /mysqllog/osw/*.sh ...
- PHP移动互联网开发笔记(2)——变量及常量
原文地址:http://www.php100.com/html/php/rumen/2014/0326/6703.html 一.PHP5.4的基本的语法格式 1.PHP的切割符 view source ...
- 【JAVA得知】struts2 于 Actionsupport 任务
尊重原创:http://xumiao900.iteye.com/blog/469760 Action 跟 Actionsupport 的差别 当我们在写action的时候,能够实现A ...
- duilib底层机制剖析:窗口类与窗口句柄的关联
转载请说明原出处.谢谢~~ 看到群里朋友有人讨论WTL中的thunk技术,让我联想到了duilib的类似技术. 这些技术都是为了解决c++封装的窗口类与窗口句柄的关联问题. 这里是三篇关于thunk技 ...