EASON ========= EASON = Easy JSON. 使用EASON能大大简化在Swift中处理JSON数据结构和从JSON数据结构到各种类的转换的各种操作。EASON包括了: - 一个JSONObject结构用来简化和优化对JSON数据结构的操作访问 - 将JSON的各种数据结构如String, Array和Dictionary 转换成JSONObject结构以便对JSON数据进行各种操作 - 一系列的工具函数和protocols来将JSONObject结构转换成自己定义的class对象 - 一套自定的operator来优化JSONObject和自定义类转换的操作 - EASON的JSON到自定义类的转换的performance优于现在流行的swift的JSON处理框架 安装 ------------ ### CocoaPods (iOS 8+) 可以通过Cocoapods来安装EASON: #### Podfile ``` platform :ios, '8.0' use_frameworks! pod 'EASON' ``` 在Project当中import: ```swift import EASON ``` ### 直接嵌入源代码 EASON是一个开源库,可以从[这里](https://github.com/jie-cao/EASON).直接找到源代码并加入项目。EASON是一个非常轻量级的框架,唯一需要嵌入项目的源代码文件是`EASON.swift` 如何使用 ---------- ### 使用 JSONObject 在安装EASON到你的项目后,你可以通过下面这些方法来把Array,Dictionary,String或者NSData转换成一个JSONObject结构的对象。在转换成JSONObject后,你可以通过下面这些方法来访问JSON数据结构中个各个对象: 将Dictionary转换成JSONObject并访问JSONObject对象: ```swift let object = ["name": "Hello", "id": 123] let jsonObject = JSONObject(object) print(jsonObject["name"].stringValue) print("\(jsonObject["id"].intValue)") ``` 将Array转会成JSONObject并访问JSONObject对象: ```swift let jsonArray:JSONObject = ["This", "is", "a", "string", 1, 2, 3, 4] print(jsonArray[0].string) print(jsonArray[1].string) print(jsonArray[2].string) print(jsonArray[3].string) print("\(jsonArray[4].intValue)") print("\(jsonArray[5].intValue)" + "\(jsonArray[6].intValue)") ``` 将String转会成JSONObject并访问JSONObject对象: ```swift public struct JSONObject { public init(string: String?) ... ``` ```swift let jsonString = "{\"name\": \"hello\", \"id\":123}" let jsonObject = JSONObject(string: jsonString) print(jsonObject["name"].stringValue) print("\(jsonObject["id"].intValue)") ``` 将NSData转会成JSONObject并访问JSONObject对象: 用下面的初始化函数来将NSData转换成JSONObject: ```swift public struct JSONObject { public init(data: NSData?) ... ``` ```swift if let path = NSBundle(forClass: BaseTests.self).pathForResource("twitter", ofType: "json") { let data: NSData? do { data = try NSData(contentsOfFile: path, options: []) } catch _ { data = nil } let jsonArray = JSONObject(data:data) for jsonObject in jsonArray{ print("\(jsonObject["id"].int)") print(jsonObject["text"].string) } } ``` ### 用下标来访问JSONObject的结构 JSON的数据结构是基于Dictionary和Array的,JSONObject提供了用下标访问JSON的各个field。例如: ```swift let jsonString = "{\"name\": \"hello\", \"id\":123}" let jsonObject = JSONObject(string: jsonString) print(jsonObject["name"].stringValue) print("\(jsonObject["id"].intValue)") ``` 对于Dictionary的子结构,下标是key。对于Array的子结构,下标是index。对于JSONObject,不要担心下标越界和访问没有的key。JSONObject结构不会抛出exception而会返回nil。 ### 用iterations来访问JSONObject 用for loop或者其他iteration方式来访问JSON数据结构中的Array中的各个元素。EASON也提供对JSONObject用iteration来访问: ```swift let data: NSData? do { data = try NSData(contentsOfFile: path, options: []) } catch _ { data = nil } let jsonArray = JSONObject(data:data) for jsonObject in jsonArray{ print("\(jsonObject["id"].int)") print(jsonObject["text"].string) } ``` ### 将JSONObject转换成自定义的类 在处理JSON数据结构时,一个常见的需求就是将API返回的JSON数据结构转换成自定义的类的对象。EASON提供了一系列的工具函数和protocol来帮助实现这一目的: 你可以用前面提供的方法将JSON数据结构转换成JSONObject, 然后通过JSONObject转换成定义的类的对象。你可以在定义的class来继承一个`JSONSerialization `的protocol。这个protocol唯一需要实现的函数是下面这个初始化函数: ```swift init?(jsonObject: JSONObject) ``` 你可以通过这个函数来实现JSONObject的子结构到自定义的类的property的一一对应关系。 下面提供了一个将Twitter的Sample JSON Response转换成一个自定义的Tweet的类例子: ```swift class Tweet: NSObject, JSONSerialization { var id:Int? var createdAt:NSDate? var user:TweetUser? var text:String? required init?(jsonObject: JSONObject) { self.id = jsonObject["id"].string self.text = jsonObject["text"].string self.createdAt = JSONObject.dateTransformer(jsonObject["created_at"], dateFormatter: "EEE MMM dd HH:mm:ss Z yyyy") self.user = JSONObject.objectTransformer(jsonObject["user"]) } } ``` ```JSONObject.objectTransformer```函数是一个Helper函数来负责讲String转换成NSDate的对象。 #### 使用```JSONObject.objectTransformer``` 函数 在上面的例子中间,我们注意到 ```user```这个proprty也是一个自定义的```TweetUser```类,在指定一对一转换关系的时候,用```JSONObject.objectTransformer``` 来帮助实现。在```TweetUser```中,只要和```Tweet```类一样继承`JSONSerialization `protocol。```TweetUser```可以如下定义: ```swift class TweetUser: NSObject, JSONSerialization { var id:Int? var name:String? var profile_image_url:NSURL? required init?(jsonObject: JSONObject) { self.name = jsonObject["name"].string self.id = jsonObject["id"].string self.profile_image_url = jsonObject["profile_image_url"].URL } } ``` #### 使用```JSONObject.arrayTransformer```函数 除了Dictionary的结构,JSON数据或者它的子结构也会是Array结构。如果想要将Array转换成自定类的一个Array,可以使用```JSONObject.arrayTransformer``` 函数。下面的一个例子是将一个包含Tweets的JSON数据转换成一个自定义的Tweet的Array。 ```swift var tweets = JSONObject.arrayTransformer(jsonObject["tweets"]) ``` 利用```JSONObject.arrayTransformer``` 和```JSONObject.objectTransformer``` ,可以将JSON数据结构转换成各个自定义的复杂或者简单的类。关于将JSON数据结构转换成自定义类的复杂引用,请参考Demo的项目中的基于Twitter的JSON Response的例子。 **下面我会会介绍几个自定义的操作符来使这一过程更加简化**。 ### 使用自定义操作符: =~ =? =! 我们主要上面的例子中,我们要访问JSONObject中的int或者string值来给赋值给自定义类中的property。EASON提供了几个自定义的操作符来大大简化这一过程。下面是这些操作符的定义: 1. =~ 操作符 这个operator的作用就是将一个JSONObject的对象转换成operator左边的类对象。但是如果这个JSONObject对象不能转换成指定的类,这个操作符不会进行任何动作。 当左边的类是一个non-optional的类T时,使用这个操作符。 2. =? 操作符 这个operator的作用就是将一个JSONObject的对象转换成operator左边的类对象。但是如果这个JSONObject对象不能转换成指定的类,这个操作符会将左边的对象设置成nil。 当左边的类是一个optional的类T?时,使用这个操作符。 3. =! 操作符 这个operator的作用就是将一个JSONObject的对象转换成operator左边的类对象。但是如果这个JSONObject对象不能转换成指定的类,这个操作符会返回这个类的指定default值。 这个操作符可以用在任何T,T?和T!类。 因为无法的事用户自定义的类的default值,所以=!操作符无法运用在用户自定义的类上。可以用=?或者=~来实现转换功能。 使用上面这个几个操作符,可以大大简化从JSONObject到自定义类的转换过程。例如上面的例子可以简化为下面的代码: ```swift class Tweet: NSObject, JSONSerialization { var id:Int? var createdAt:NSDate? var user:TweetUser? var text:String? required init?(jsonObject: JSONObject) { self.id =? jsonObject["id"] self.text =? jsonObject["text"] self.user =? jsonObject["user"] // Use custom transformer to convert string to NSDate self.createdAt = JSONObject.dateTransformer(jsonObject["created_at"], dateFormatter: "EEE MMM dd HH:mm:ss Z yyyy") } } ``` ```swift class TweetUser: NSObject, JSONSerialization { var id:Int? var name:String? var profile_image_url:NSURL? required init?(jsonObject: JSONObject) { self.name =? jsonObject["name"] self.id =? jsonObject["id"] self.profile_image_url =? jsonObject["profile_image_url"] } } ``` ## Licenses All source code is licensed under the [MIT License](https://raw.github.com/rs/SDWebImage/master/LICENSE).