diff --git a/JSONHelper.podspec b/JSONHelper.podspec index 7b76bf8..5dda195 100644 --- a/JSONHelper.podspec +++ b/JSONHelper.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'JSONHelper' - s.version = '1.4.2' + s.version = '1.5.0' s.license = { :type => 'zlib', :file => 'LICENSE' } s.summary = 'Lightning fast JSON deserialization and value conversion library for iOS & OS X written in Swift.' diff --git a/JSONHelper/JSONHelper.swift b/JSONHelper/JSONHelper.swift index a637cf1..d590ed6 100644 --- a/JSONHelper/JSONHelper.swift +++ b/JSONHelper/JSONHelper.swift @@ -34,12 +34,13 @@ import Foundation /// type of object as a value. public typealias JSONDictionary = [String: AnyObject] -// MARK: Operator for quick primitive type deserialization. +/// Operator for use in deserialization operations. +infix operator <-- { associativity right precedence 150 } -infix operator <<< { associativity right precedence 150 } +/// MARK: Primitive Type Deserialization // For optionals. -public func <<< (inout property: T?, value: AnyObject?) -> T? { +public func <-- (inout property: T?, value: AnyObject?) -> T? { var newValue: T? if let unwrappedValue: AnyObject = value { // We unwrapped the given value successfully, try to convert. @@ -75,15 +76,15 @@ public func <<< (inout property: T?, value: AnyObject?) -> T? { } // For non-optionals. -public func <<< (inout property: T, value: AnyObject?) -> T { +public func <-- (inout property: T, value: AnyObject?) -> T { var newValue: T? - newValue <<< value + newValue <-- value if let newValue = newValue { property = newValue } return property } // Special handling for value and format pair to NSDate conversion. -public func <<< (inout property: NSDate?, valueAndFormat: (value: AnyObject?, format: AnyObject?)) -> NSDate? { +public func <-- (inout property: NSDate?, valueAndFormat: (value: AnyObject?, format: AnyObject?)) -> NSDate? { var newValue: NSDate? if let dateString = valueAndFormat.value as? String { if let formatString = valueAndFormat.format as? String { @@ -98,18 +99,16 @@ public func <<< (inout property: NSDate?, valueAndFormat: (value: AnyObject?, fo return property } -public func <<< (inout property: NSDate, valueAndFormat: (value: AnyObject?, format: AnyObject?)) -> NSDate { +public func <-- (inout property: NSDate, valueAndFormat: (value: AnyObject?, format: AnyObject?)) -> NSDate { var date: NSDate? - date <<< valueAndFormat + date <-- valueAndFormat if let date = date { property = date } return property } -// MARK: Operator for quick primitive array deserialization. +// MARK: Primitive Array Deserialization -infix operator <<<* { associativity right precedence 150 } - -public func <<<* (inout array: [String]?, value: AnyObject?) -> [String]? { +public func <-- (inout array: [String]?, value: AnyObject?) -> [String]? { if let stringArray = value as? [String] { array = stringArray } else { @@ -118,14 +117,14 @@ public func <<<* (inout array: [String]?, value: AnyObject?) -> [String]? { return array } -public func <<<* (inout array: [String], value: AnyObject?) -> [String] { +public func <-- (inout array: [String], value: AnyObject?) -> [String] { var newValue: [String]? - newValue <<<* value + newValue <-- value if let newValue = newValue { array = newValue } return array } -public func <<<* (inout array: [Int]?, value: AnyObject?) -> [Int]? { +public func <-- (inout array: [Int]?, value: AnyObject?) -> [Int]? { if let intArray = value as? [Int] { array = intArray } else { @@ -134,14 +133,14 @@ public func <<<* (inout array: [Int]?, value: AnyObject?) -> [Int]? { return array } -public func <<<* (inout array: [Int], value: AnyObject?) -> [Int] { +public func <-- (inout array: [Int], value: AnyObject?) -> [Int] { var newValue: [Int]? - newValue <<<* value + newValue <-- value if let newValue = newValue { array = newValue } return array } -public func <<<* (inout array: [Float]?, value: AnyObject?) -> [Float]? { +public func <-- (inout array: [Float]?, value: AnyObject?) -> [Float]? { if let floatArray = value as? [Float] { array = floatArray @@ -151,14 +150,14 @@ public func <<<* (inout array: [Float]?, value: AnyObject?) -> [Float]? { return array } -public func <<<* (inout array: [Float], value: AnyObject?) -> [Float] { +public func <-- (inout array: [Float], value: AnyObject?) -> [Float] { var newValue: [Float]? - newValue <<<* value + newValue <-- value if let newValue = newValue { array = newValue } return array } -public func <<<* (inout array: [Double]?, value: AnyObject?) -> [Double]? { +public func <-- (inout array: [Double]?, value: AnyObject?) -> [Double]? { if let doubleArrayDoubleExcitement = value as? [Double] { array = doubleArrayDoubleExcitement } else { @@ -167,14 +166,14 @@ public func <<<* (inout array: [Double]?, value: AnyObject?) -> [Double]? { return array } -public func <<<* (inout array: [Double], value: AnyObject?) -> [Double] { +public func <-- (inout array: [Double], value: AnyObject?) -> [Double] { var newValue: [Double]? - newValue <<<* value + newValue <-- value if let newValue = newValue { array = newValue } return array } -public func <<<* (inout array: [Bool]?, value: AnyObject?) -> [Bool]? { +public func <-- (inout array: [Bool]?, value: AnyObject?) -> [Bool]? { if let boolArray = value as? [Bool] { array = boolArray } else { @@ -183,14 +182,14 @@ public func <<<* (inout array: [Bool]?, value: AnyObject?) -> [Bool]? { return array } -public func <<<* (inout array: [Bool], value: AnyObject?) -> [Bool] { +public func <-- (inout array: [Bool], value: AnyObject?) -> [Bool] { var newValue: [Bool]? - newValue <<<* value + newValue <-- value if let newValue = newValue { array = newValue } return array } -public func <<<* (inout array: [NSURL]?, value: AnyObject?) -> [NSURL]? { +public func <-- (inout array: [NSURL]?, value: AnyObject?) -> [NSURL]? { if let stringURLArray = value as? [String] { array = [NSURL]() for stringURL in stringURLArray { @@ -204,14 +203,14 @@ public func <<<* (inout array: [NSURL]?, value: AnyObject?) -> [NSURL]? { return array } -public func <<<* (inout array: [NSURL], value: AnyObject?) -> [NSURL] { +public func <-- (inout array: [NSURL], value: AnyObject?) -> [NSURL] { var newValue: [NSURL]? - newValue <<<* value + newValue <-- value if let newValue = newValue { array = newValue } return array } -public func <<<* (inout array: [NSDate]?, valueAndFormat: (value: AnyObject?, format: AnyObject?)) -> [NSDate]? { +public func <-- (inout array: [NSDate]?, valueAndFormat: (value: AnyObject?, format: AnyObject?)) -> [NSDate]? { var newValue: [NSDate]? if let dateStringArray = valueAndFormat.value as? [String] { if let formatString = valueAndFormat.format as? String { @@ -229,21 +228,19 @@ public func <<<* (inout array: [NSDate]?, valueAndFormat: (value: AnyObject?, fo return array } -public func <<<* (inout array: [NSDate], valueAndFormat: (value: AnyObject?, format: AnyObject?)) -> [NSDate] { +public func <-- (inout array: [NSDate], valueAndFormat: (value: AnyObject?, format: AnyObject?)) -> [NSDate] { var newValue: [NSDate]? - newValue <<<* valueAndFormat + newValue <-- valueAndFormat if let newValue = newValue { array = newValue } return array } -public func <<<* (inout array: [NSDate]?, value: AnyObject?) -> [NSDate]? { - +public func <-- (inout array: [NSDate]?, value: AnyObject?) -> [NSDate]? { if let timestamps = value as? [AnyObject] { array = [NSDate]() - for timestamp in timestamps { var date: NSDate? - date <<< timestamp + date <-- timestamp if date != nil { array!.append(date!) } } } else { @@ -252,22 +249,20 @@ public func <<<* (inout array: [NSDate]?, value: AnyObject?) -> [NSDate]? { return array } -public func <<<* (inout array: [NSDate], value: AnyObject?) -> [NSDate] { +public func <-- (inout array: [NSDate], value: AnyObject?) -> [NSDate] { var newValue: [NSDate]? - newValue <<<* value + newValue <-- value if let newValue = newValue { array = newValue } return array } -// MARK: Operator for quick class deserialization. - -infix operator <<<< { associativity right precedence 150 } +// MARK: Custom Object Deserialization public protocol Deserializable { init(data: JSONDictionary) } -public func <<<< (inout instance: T?, dataObject: AnyObject?) -> T? { +public func <-- (inout instance: T?, dataObject: AnyObject?) -> T? { if let data = dataObject as? JSONDictionary { instance = T(data: data) } else { @@ -276,18 +271,16 @@ public func <<<< (inout instance: T?, dataObject: AnyObject?) return instance } -public func <<<< (inout instance: T, dataObject: AnyObject?) -> T { +public func <-- (inout instance: T, dataObject: AnyObject?) -> T { var newInstance: T? - newInstance <<<< dataObject + newInstance <-- dataObject if let newInstance = newInstance { instance = newInstance } return instance } -// MARK: Operator for quick deserialization into an array of instances of a deserializable class. - -infix operator <<<<* { associativity right precedence 150 } +// MARK: Custom Object Array Deserialization -public func <<<<* (inout array: [T]?, dataObject: AnyObject?) -> [T]? { +public func <-- (inout array: [T]?, dataObject: AnyObject?) -> [T]? { if let dataArray = dataObject as? [JSONDictionary] { array = [T]() for data in dataArray { @@ -299,14 +292,14 @@ public func <<<<* (inout array: [T]?, dataObject: AnyObject?) return array } -public func <<<<* (inout array: [T], dataObject: AnyObject?) -> [T] { +public func <-- (inout array: [T], dataObject: AnyObject?) -> [T] { var newArray: [T]? - newArray <<<<* dataObject + newArray <-- dataObject if let newArray = newArray { array = newArray } return array } -// MARK: Overloading of own operators for deserialization of JSON strings. +// MARK: JSON String Deserialization private func dataStringToObject(dataString: String) -> AnyObject? { var data: NSData = dataString.dataUsingEncoding(NSUTF8StringEncoding)! @@ -314,18 +307,18 @@ private func dataStringToObject(dataString: String) -> AnyObject? { return NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: &error) } -public func <<<< (inout instance: T?, dataString: String) -> T? { - return instance <<<< dataStringToObject(dataString) +public func <-- (inout instance: T?, dataString: String) -> T? { + return instance <-- dataStringToObject(dataString) } -public func <<<< (inout instance: T, dataString: String) -> T { - return instance <<<< dataStringToObject(dataString) +public func <-- (inout instance: T, dataString: String) -> T { + return instance <-- dataStringToObject(dataString) } -public func <<<<* (inout array: [T]?, dataString: String) -> [T]? { - return array <<<<* dataStringToObject(dataString) +public func <-- (inout array: [T]?, dataString: String) -> [T]? { + return array <-- dataStringToObject(dataString) } -public func <<<<* (inout array: [T], dataString: String) -> [T] { - return array <<<<* dataStringToObject(dataString) +public func <-- (inout array: [T], dataString: String) -> [T] { + return array <-- dataStringToObject(dataString) } diff --git a/JSONHelper/Supporting Files/Mac/Info.plist b/JSONHelper/Supporting Files/Mac/Info.plist index b0a4c4d..f24ce9a 100644 --- a/JSONHelper/Supporting Files/Mac/Info.plist +++ b/JSONHelper/Supporting Files/Mac/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.4.2 + 1.5.0 CFBundleSignature ???? CFBundleVersion - 11 + 12 NSPrincipalClass diff --git a/JSONHelper/Supporting Files/iOS/Info.plist b/JSONHelper/Supporting Files/iOS/Info.plist index b0a4c4d..f24ce9a 100644 --- a/JSONHelper/Supporting Files/iOS/Info.plist +++ b/JSONHelper/Supporting Files/iOS/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.4.2 + 1.5.0 CFBundleSignature ???? CFBundleVersion - 11 + 12 NSPrincipalClass diff --git a/JSONHelperTests/JSONHelperTests.swift b/JSONHelperTests/JSONHelperTests.swift index 837161d..1ba6582 100644 --- a/JSONHelperTests/JSONHelperTests.swift +++ b/JSONHelperTests/JSONHelperTests.swift @@ -33,11 +33,11 @@ class JSONHelperTests: XCTestCase { ] ] - class Person: Deserializable { + struct Person: Deserializable { var name = "" - required init(data: [String: AnyObject]) { - name <<< data["name"] + init(data: [String: AnyObject]) { + name <-- data["name"] } init() {} @@ -45,72 +45,72 @@ class JSONHelperTests: XCTestCase { func testOptionalString() { var property: String? - property <<< dummyResponse["string"] + property <-- dummyResponse["string"] XCTAssertEqual(property!, "a", "String? property should equal 'a'") - property <<< dummyResponse["invalidKey"] + property <-- dummyResponse["invalidKey"] XCTAssertNil(property, "String? property should equal nil after invalid assignment") } func testString() { var property = "b" - property <<< dummyResponse["invalidKey"] + property <-- dummyResponse["invalidKey"] XCTAssertEqual(property, "b", "String property should have the default value 'b'") - property <<< dummyResponse["string"] + property <-- dummyResponse["string"] XCTAssertEqual(property, "a", "String property should equal 'a'") } func testOptionalInt() { var property: Int? - property <<< dummyResponse["int"] + property <-- dummyResponse["int"] XCTAssertEqual(property!, 1, "Int? property should equal 1") - property <<< dummyResponse["invalidKey"] + property <-- dummyResponse["invalidKey"] XCTAssertNil(property, "Int? property should equal nil after invalid assignment") } func testInt() { var property = 2 - property <<< dummyResponse["invalidKey"] + property <-- dummyResponse["invalidKey"] XCTAssertEqual(property, 2, "Int property should have the default value 2") - property <<< dummyResponse["int"] + property <-- dummyResponse["int"] XCTAssertEqual(property, 1, "Int property should equal 1") } func testStringToOptionalInt() { var number: Int? - number <<< dummyResponse["int_string"] + number <-- dummyResponse["int_string"] XCTAssertEqual(number!, 1, "Strings containing numbers should successfully deserialize into optional Ints.") } func testStringToInt() { var number = 0 - number <<< dummyResponse["int_string"] + number <-- dummyResponse["int_string"] XCTAssertEqual(number, 1, "Strings containing numbers should successfully deserialize into Ints.") } func testOptionalBool() { var property: Bool? - property <<< dummyResponse["bool"] + property <-- dummyResponse["bool"] XCTAssertEqual(property!, true, "Bool? property should equal true") - property <<< dummyResponse["invalidKey"] + property <-- dummyResponse["invalidKey"] XCTAssertNil(property, "Bool? property should equal nil after invalid assignment") } func testBool() { var property = true - property <<< dummyResponse["invalidKey"] + property <-- dummyResponse["invalidKey"] XCTAssertEqual(property, true, "Bool property should have the default value true") - property <<< dummyResponse["bool"] + property <-- dummyResponse["bool"] XCTAssertEqual(property, true, "Bool property should equal true") } func testOptionalNSDate() { var property: NSDate? - property <<< (value: dummyResponse["date"], format: "yyyy-MM-dd") + property <-- (value: dummyResponse["date"], format: "yyyy-MM-dd") let dateFormatter = NSDateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" let testDate = dateFormatter.dateFromString("2014-09-19") XCTAssertEqual(property!.compare(testDate!), NSComparisonResult.OrderedSame, "NSDate? property should equal 2014-09-19") - property <<< dummyResponse["invalidKey"] + property <-- dummyResponse["invalidKey"] XCTAssertNil(property, "NSDate? property should equal nil after invalid assignment") } @@ -119,56 +119,56 @@ class JSONHelperTests: XCTestCase { dateFormatter.dateFormat = "yyyy-MM-dd" let defaultTestDate = dateFormatter.dateFromString("2015-09-19") var property = defaultTestDate! - property <<< (value: dummyResponse["invalidKey"], format: "yyyy-MM-dd") + property <-- (value: dummyResponse["invalidKey"], format: "yyyy-MM-dd") XCTAssertEqual(property.compare(defaultTestDate!), NSComparisonResult.OrderedSame, "NSDate should have the default value 2015-09-19") - property <<< (value: dummyResponse["date"], format: "yyyy-MM-dd") + property <-- (value: dummyResponse["date"], format: "yyyy-MM-dd") let testDate = dateFormatter.dateFromString("2014-09-19") XCTAssertEqual(property.compare(testDate!), NSComparisonResult.OrderedSame, "NSDate should have the value 2015-09-19") } func testOptionalNSURL() { var property: NSURL? - property <<< dummyResponse["url"] + property <-- dummyResponse["url"] XCTAssertEqual(property!.host!, "github.com", "NSURL? property should equal github.com") - property <<< dummyResponse["invalidKey"] + property <-- dummyResponse["invalidKey"] XCTAssertNil(property, "NSURL? property should equal nil after invalid assignment") } func testNSURL() { var property = NSURL(string: "http://google.com")! - property <<< dummyResponse["invalidKey"] + property <-- dummyResponse["invalidKey"] XCTAssertEqual(property.host!, "google.com", "NSURL should have the default value google.com") - property <<< dummyResponse["url"] + property <-- dummyResponse["url"] XCTAssertEqual(property.host!, "github.com", "NSURL should have the value github.com") } func testStringArray() { var property = [String]() - property <<<* dummyResponse["stringArray"] + property <-- dummyResponse["stringArray"] XCTAssertEqual(property.count, 3, "[String] property should have 3 members") } func testIntArray() { var property = [Int]() - property <<<* dummyResponse["intArray"] + property <-- dummyResponse["intArray"] XCTAssertEqual(property.count, 5, "[Int] property should have 5 members") } func testBoolArray() { var property = [Bool]() - property <<<* dummyResponse["boolArray"] + property <-- dummyResponse["boolArray"] XCTAssertEqual(property.count, 2, "[Bool] property should have 2 members") } func testInstance() { var instance = Person() - instance <<<< dummyResponse["instance"] + instance <-- dummyResponse["instance"] XCTAssertEqual(instance.name, "b", "Person instance's name property should equal 'b'") } func testInstanceArray() { var property = [Person]() - property <<<<* dummyResponse["instanceArray"] + property <-- dummyResponse["instanceArray"] XCTAssertEqual(property.count, 2, "[Person] property should have 2 members") } @@ -177,7 +177,7 @@ class JSONHelperTests: XCTestCase { var people = [Person]() var areYouGroot = "" - people <<<<* jsonString + people <-- jsonString for person in people { areYouGroot += person.name diff --git a/README.md b/README.md index 383bda3..697b33c 100644 --- a/README.md +++ b/README.md @@ -48,18 +48,9 @@ pod "JSONHelper" You can also add [JSONHelper.swift](https://raw.githubusercontent.com/isair/JSONHelper/master/JSONHelper/JSONHelper.swift) directly into your project. -##Operator List - -| Operator | Functionality | -| --------- | ---------------------------------------------------------------------------------------------------------- | -| __<<<__ | For deserializing data into primitive types, NSDate or NSURL. | -| __<<<*__ | For deserializing data into an array of primitive types, NSDate or NSURL. | -| __<<<<__ | For deserializing data into an instance of a class. __Supports JSON strings__ | -| __<<<<*__ | For deserializing data into an array that contains instances of a certain class. __Supports JSON strings__ | - ##Simple Tutorial -Please take a good look at the operator list before you start reading this tutorial. Also, for simplicity, I'm going to assume you use [AFNetworking](https://github.com/AFNetworking/AFNetworking) as your networking library. Let's say we have an endpoint at __http://yoursite.com/your-endpoint/__ which gives the following response when a simple __GET__ request is sent to it. +First of all I'm going to assume you use [AFNetworking](https://github.com/AFNetworking/AFNetworking) as your networking library; for simplicity. Let's say we have an endpoint at __http://yoursite.com/your-endpoint/__ which gives the following response when a simple __GET__ request is sent to it. ```json { @@ -85,7 +76,7 @@ internal struct Book { } ``` -We now have to make it extend the protocol __Deserializable__ and implement the __required init(data: [String: AnyObject])__ initializer. The complete model should look like this: +We now have to make it extend the protocol __Deserializable__ and implement the __required init(data: [String: AnyObject])__ initializer and use our deserialization operator (`<--`) in it. The complete model should look like this: ```swift internal struct Book: Deserializable { @@ -93,8 +84,8 @@ internal struct Book: Deserializable { var name: String? init(data: [String: AnyObject]) { - author <<< data["author"] - name <<< data["name"] + author <-- data["author"] + name <-- data["name"] } } ``` @@ -107,7 +98,7 @@ AFHTTPRequestOperationManager().GET( parameters: nil, success: { operation, data in var books: [Book]? - books <<<<* data["books"] + books <-- data["books"] if let books = books { // Response contained a books array, and we deserialized it. Do what you want here. @@ -130,32 +121,32 @@ internal struct User: Deserializable { var name = "Guest" required init(data: [String: AnyObject]) { - name <<< data["name"] + name <-- data["name"] } } ```` ##NSDate and NSURL Deserialization -The __<<<__ and __<<<*__ operators also support deserializing data into NSDate and NSURL variables. +You can also deserialize data into NSDate and NSURL variables, or arrays of them. ````swift let website: NSURL? let imageURLs: [NSURL]? -website <<< "http://mywebsite.com" -imageURLs <<<* ["http://mywebsite.com/image.png", "http://mywebsite.com/anotherImage.png"] +website <-- "http://mywebsite.com" +imageURLs <-- ["http://mywebsite.com/image.png", "http://mywebsite.com/anotherImage.png"] ```` ````swift let meetingDate: NSDate? let partyDates: [NSDate]? -meetingDate <<< (value: "2014-09-18", format: "yyyy-MM-dd") -partyDates <<<* (value: ["2014-09-19", "2014-09-20"], format: "yyyy-MM-dd") +meetingDate <-- (value: "2014-09-18", format: "yyyy-MM-dd") +partyDates <-- (value: ["2014-09-19", "2014-09-20"], format: "yyyy-MM-dd") let myDayOff: NSDate? -myDayOff <<< 1414172803 // You can also use unix timestamps. +myDayOff <-- 1414172803 // You can also use unix timestamps. ```` ##JSON String Deserialization @@ -167,14 +158,14 @@ internal struct Person: Deserializable { var name = "" init(data: [String: AnyObject]) { - name <<< data["name"] + name <-- data["name"] } } var jsonString = "[{\"name\": \"Rocket Raccoon\"}, {\"name\": \"Groot\"}]" var people = [Person]() -people <<<<* jsonString +people <-- jsonString for person in people { println("\(person.name)")