TestsTested | ✓ |
LangLanguage | SwiftSwift |
License | MIT |
ReleasedLast Release | Apr 2016 |
SPMSupports SPM | ✗ |
Maintained by Jie Cao.
EASON = Easy JSON. It simplifies JSON deserialization in Swift. It provides:
platform :ios, '8.0'
use_frameworks!
pod 'EASON'
In the project, you can import the EASON framework
import EASON
The source code from here. You can manually add the source code into your project. There is only one file you need to import:EASON.swift
After import, you can covert your JSON instance from Array, Dictionary, String or NSData into a JSONObject instance. The JSONObject instance is the main object you can interact with: For example:
Covert Dictionary to JSONObject
let object = ["name": "Hello", "id": 123]
let jsonObject = JSONObject(object)
print(jsonObject["name"].stringValue)
print("\(jsonObject["id"].intValue)")
Covert Array to JSONObject
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)")
Covert String to JSONObject
use the following initialization function for converting String to JSONObject:
public struct JSONObject {
public init(string: String?)
...
let jsonString = "{\"name\": \"hello\", \"id\":123}"
let jsonObject = JSONObject(string: jsonString)
print(jsonObject["name"].stringValue)
print("\(jsonObject["id"].intValue)")
Covert NSData to JSONObject use the following initialization function for converting NSData to JSONObject:
public struct JSONObject {
public init(data: NSData?)
...
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)
}
}
The fields in JSONObject can be accessed using subscript. For example:
let jsonString = "{\"name\": \"hello\", \"id\":123}"
let jsonObject = JSONObject(string: jsonString)
print(jsonObject["name"].stringValue)
print("\(jsonObject["id"].intValue)")
Don’t worry about accessing use subscript value that is out of the bound of the array or dictionary. It will not thrown exception and will return nil in these cases.
It is very common that the JSON object is an Array. You can use loop to iterate the elements in the array:
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)
}
A very common task is to convert a JSON response from the web service into user-defined class instances. EASON provides a set of Utils methods and protocol to help complete this task. You can add the JSONSerialization
protocol to the class you defined. You will need to implement the required init:
init?(jsonObject: JSONObject)
In the init method, you can define the relationship between fields in JSON and properties in your class. For example, I have defined a class to represent a tweet in Twitter:
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"])
}
}
The JSONObject.dateTransformer
method is a helper class to convert string to NSDate object.
Noticed that the user
property in Tweet
class is also a user-defined class instance to the the field to a TweetUser
instance.
TheTweetUser
class needs to implementJSONSerialization
protocol as well. After that, you can use the helper method JSONObject.objectTransformer
to transform the user
field to user
with TweetUser
class. The TweetUser
class is defined as follows:
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
}
}
In some cases, you want to convert the sub-fields in a JSON response into an array of user-defined class objects. You can use the JSONObject.arrayTransformer
helper method to achieve this. For example, if you want to convert a sub-field in a JSON response to an Array of [Tweet] object, you can use the following command
var tweets = JSONObject.arrayTransformer(jsonObject["tweets"])
Follow this pattern, the JSON response can be transformed into user-defined class with multiple layers. Please see the examples for deserialize tweets from a sample response from Twitter in the Demo project.
In the next section, we will use custom operators to simplies this process.
Noticed that in the previous section, we need to decide whether we need to assign string or int value for fields in the class. You can simplify this by using the following custom operators. Their definitions are:
=~ operator
If the JSONObject instance can be converted to the given class, assign the instance object with class with the converted value. The operator will do nothing if the JSONObject instance cannot be converted to an object with the given class. Use the operator to convert the JSONOjbect instance to any non-optional type T
=? operator
If the JSONObject instance can be converted to the given class, assign the instance object with class with the converted value. The operator will assign the the left hand side objet to nil if the JSONObject instance cannot be converted to an object with the given class. Use this operator to covert the JSONObject instance to any optional Type T?
=! operator
If the JSONObject instance can be converted to the given class, assign the instance object with class with the converted value. The operator will assign the the left hand side objet to the default value of for the given class. If the JSONObject instance cannot be converted to an object with the given class. This operator can be used to convert the JSONObject intance to any type T, T? or T! Since EASON does not know the default value for user-defined class, =! cannot be used for user-defined class. You can use =? or =~ for the conversion.
Using the custom operators, the transformation process in the previous section can be simplified as follows:
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")
}
}
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"]
}
}
All source code is licensed under the MIT License.