在Swift中优雅地处理JSON

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

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. var string: String? 
  2. var number: NSNumber? 
  3. var bool: Bool?  
  4. var array: Array<JSONValue>? 
  5. var object: Dictionary<String, JSONValue>? 

注意每一种属性都是一个Optional值。这是因为JSON数据能包含任何它定义的有效类型。

因此,建议的方式是用Optional绑定检索值:

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

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

  1. if let intValue = numberValue.integer{ 
  2.     count += intValue 

枚举(Enumeration)

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

  1. enum JSONValue { 
  2.   
  3.     case JNumber(NSNumber) 
  4.     case JString(String) 
  5.     case JBool(Bool) 
  6.     case JNull 
  7.     case JArray(Array<JSONValue>) 
  8.     case JObject(Dictionary<String,JSONValue>) 
  9.     case JInvalid(NSError) 
  10.   

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

  1. let json = JSONValue(jsonObject) 
  2. switch json["user_id"]{ 
  3. case .JString(let stringValue): 
  4.     let id = stringValue.toInt() 
  5. case .JNumber(let numberValue): 
  6.     let id = numberValue.integerValue 
  7. default
  8.     println("ooops!!! JSON Data is Unexpected or Broken"

下标(Subscripts)

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

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

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

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

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

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

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

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

打印

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

  1. let json = JSONValue(dataFromNetwork) 
  2. println(json) 
  3. /*You can get a well printed human readable raw JSON string: 
  4.       { 
  5.         "url": { 
  6.           "urls": [ 
  7.             { 
  8.               "expanded_url": null, 
  9.               "url": "http://bit.ly/oauth-dancer", 
  10.               "indices": [ 
  11.                 0, 
  12.                 26 
  13.               ], 
  14.               "display_url": null 
  15.             } 
  16.           ] 
  17.        } 
  18. */ 

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

  1. let printableString = json.description 

调试与错误处理

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

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

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

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

后记

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

本文链接:http://mobile.51cto.com/design-446157.htm

责任编辑:chenqingxiang 来源: oschina
相关推荐

2023-05-12 12:09:38

职责链模式客服

2024-01-15 08:09:44

Fluent错误代码

2023-08-29 07:35:15

2022-08-03 08:41:30

客户端操作并发请求

2021-10-26 10:28:41

开发架构Kubernetes

2009-12-11 17:39:47

VS 2008数据

2014-07-04 09:47:24

SwiftSwift开发

2017-04-12 11:16:08

Python终端编程

2022-06-27 09:00:55

SwiftGit Hooks

2021-09-08 09:41:09

开发Go代码

2019-03-11 09:18:20

Java 8Stream数据结构

2023-10-05 12:43:48

数据处理

2019-12-25 10:55:00

安全数据安全互联网

2020-09-25 11:30:20

Java判空代码

2020-04-10 10:22:12

Java判空编程语言

2013-12-25 10:08:42

ember.js异步处理

2022-06-09 10:42:47

GoJSON

2023-10-07 08:34:27

项目API接口

2023-05-04 07:43:47

MySQL数据库

2015-08-06 13:44:21

swiftcocoapods
点赞
收藏

51CTO技术栈公众号