From 9967b14f4d6e879ab24a68a8cca052070866a995 Mon Sep 17 00:00:00 2001 From: Baris Sencan Date: Fri, 15 Apr 2016 13:58:25 -0700 Subject: [PATCH] Complete the rest of the tests and functionality Except serialization and JSON API support. --- JSONHelper.podspec | 4 +- JSONHelper.xcodeproj/project.pbxproj | 68 ++++++---- JSONHelper/Conversion.swift | 12 ++ JSONHelper/Extensions/Color.swift | 4 + JSONHelper/Extensions/NSURL.swift | 6 +- JSONHelper/Support/JSONAPI.swift | 143 +++++++++++----------- JSONHelperTests/DeserializableTests.swift | 41 +++++++ JSONHelperTests/JSONHelperTests.swift | 132 ++------------------ JSONHelperTests/NSURLTests.swift | 2 +- 9 files changed, 192 insertions(+), 220 deletions(-) create mode 100644 JSONHelperTests/DeserializableTests.swift diff --git a/JSONHelper.podspec b/JSONHelper.podspec index 6eb65a5..e8c9424 100644 --- a/JSONHelper.podspec +++ b/JSONHelper.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'JSONHelper' - s.version = '1.7.0' + s.version = '2.0.0' s.license = { :type => 'zlib', :file => 'LICENSE' } s.summary = 'Lightning fast JSON deserialization and value conversion library for iOS & OS X written in Swift.' @@ -12,7 +12,7 @@ Pod::Spec.new do |s| s.osx.deployment_target = '10.9' s.tvos.deployment_target = '9.0' s.source = { :git => 'https://github.com/isair/JSONHelper.git', :tag => s.version } - s.source_files = 'JSONHelper' + s.source_files = 'JSONHelper/**/*.swift' s.frameworks = 'Foundation' s.requires_arc = true end diff --git a/JSONHelper.xcodeproj/project.pbxproj b/JSONHelper.xcodeproj/project.pbxproj index d0b79d6..705a22e 100644 --- a/JSONHelper.xcodeproj/project.pbxproj +++ b/JSONHelper.xcodeproj/project.pbxproj @@ -18,23 +18,17 @@ 5F31FF5E1C533AE000EF50C4 /* Deserialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF5D1C533AE000EF50C4 /* Deserialization.swift */; }; 5F31FF601C533E9900EF50C4 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF5F1C533E9900EF50C4 /* Color.swift */; }; 5F31FF611C533E9900EF50C4 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF5F1C533E9900EF50C4 /* Color.swift */; }; - 5F31FF621C533E9900EF50C4 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF5F1C533E9900EF50C4 /* Color.swift */; }; 5F31FF631C533E9D00EF50C4 /* Deserialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF5D1C533AE000EF50C4 /* Deserialization.swift */; }; 5F31FF641C533E9D00EF50C4 /* Deserialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF5D1C533AE000EF50C4 /* Deserialization.swift */; }; 5F31FF651C533EA000EF50C4 /* Conversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF5B1C533AD400EF50C4 /* Conversion.swift */; }; 5F31FF661C533EA100EF50C4 /* Conversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF5B1C533AD400EF50C4 /* Conversion.swift */; }; - 5F31FF691C533EAA00EF50C4 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC1A4861B1CFFB500EF50C4 /* String.swift */; }; - 5F31FF6A1C533EAD00EF50C4 /* Int.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC1A4881B1D024500EF50C4 /* Int.swift */; }; 5F31FF6C1C533F1600EF50C4 /* ColorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF6B1C533F1600EF50C4 /* ColorTests.swift */; }; 5F31FF6E1C5348F000EF50C4 /* NSDecimalNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF6D1C5348F000EF50C4 /* NSDecimalNumber.swift */; }; 5F31FF6F1C5348F000EF50C4 /* NSDecimalNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF6D1C5348F000EF50C4 /* NSDecimalNumber.swift */; }; - 5F31FF701C5348F000EF50C4 /* NSDecimalNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF6D1C5348F000EF50C4 /* NSDecimalNumber.swift */; }; 5F31FF721C5348FE00EF50C4 /* Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF711C5348FE00EF50C4 /* Double.swift */; }; 5F31FF731C5348FE00EF50C4 /* Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF711C5348FE00EF50C4 /* Double.swift */; }; - 5F31FF741C5348FE00EF50C4 /* Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF711C5348FE00EF50C4 /* Double.swift */; }; 5F31FF761C53490B00EF50C4 /* Float.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF751C53490B00EF50C4 /* Float.swift */; }; 5F31FF771C53490B00EF50C4 /* Float.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF751C53490B00EF50C4 /* Float.swift */; }; - 5F31FF781C53490B00EF50C4 /* Float.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF751C53490B00EF50C4 /* Float.swift */; }; 5F31FF7A1C53496B00EF50C4 /* DoubleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF791C53496B00EF50C4 /* DoubleTests.swift */; }; 5F31FF7C1C53497600EF50C4 /* FloatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF7B1C53497600EF50C4 /* FloatTests.swift */; }; 5F31FF7E1C53499000EF50C4 /* NSDecimalNumberTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF7D1C53499000EF50C4 /* NSDecimalNumberTests.swift */; }; @@ -44,6 +38,7 @@ 5F6A2F4E1CC096DA00EF50C4 /* Serialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F6A2F4D1CC096DA00EF50C4 /* Serialization.swift */; }; 5F6A2F4F1CC096DA00EF50C4 /* Serialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F6A2F4D1CC096DA00EF50C4 /* Serialization.swift */; }; 5F6A2F501CC096DA00EF50C4 /* Serialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F6A2F4D1CC096DA00EF50C4 /* Serialization.swift */; }; + 5F6A2F531CC09B9A00EF50C4 /* DeserializableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F6A2F521CC09B9A00EF50C4 /* DeserializableTests.swift */; }; 5F8F88231CA5F32E00EF50C4 /* DictionaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F8F88221CA5F32E00EF50C4 /* DictionaryTests.swift */; }; 5F8F88251CA5F33500EF50C4 /* EnumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F8F88241CA5F33500EF50C4 /* EnumTests.swift */; }; 5F928D991C0D469F00EF50C4 /* JSONHelper-tvOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F928D981C0D469F00EF50C4 /* JSONHelper-tvOS.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -67,6 +62,15 @@ 5FC1A4941B1D1D8B00EF50C4 /* NSURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC1A4931B1D1D8B00EF50C4 /* NSURL.swift */; }; 5FC1A4951B1D1D8B00EF50C4 /* NSURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC1A4931B1D1D8B00EF50C4 /* NSURL.swift */; }; 5FD3A0A01CA5F5C300EF50C4 /* ArrayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FD3A09F1CA5F5C300EF50C4 /* ArrayTests.swift */; }; + 5FDBD51A1CC46C2A00EF50C4 /* Bool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC1A48D1B1D057B00EF50C4 /* Bool.swift */; }; + 5FDBD51B1CC46C2A00EF50C4 /* Int.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC1A4881B1D024500EF50C4 /* Int.swift */; }; + 5FDBD51C1CC46C2A00EF50C4 /* Float.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF751C53490B00EF50C4 /* Float.swift */; }; + 5FDBD51D1CC46C2A00EF50C4 /* Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF711C5348FE00EF50C4 /* Double.swift */; }; + 5FDBD51E1CC46C2A00EF50C4 /* NSDecimalNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF6D1C5348F000EF50C4 /* NSDecimalNumber.swift */; }; + 5FDBD51F1CC46C2A00EF50C4 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC1A4861B1CFFB500EF50C4 /* String.swift */; }; + 5FDBD5201CC46C2A00EF50C4 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F31FF5F1C533E9900EF50C4 /* Color.swift */; }; + 5FDBD5211CC46C2A00EF50C4 /* NSDate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC1A48F1B1D082500EF50C4 /* NSDate.swift */; }; + 5FDBD5221CC46C2A00EF50C4 /* NSURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC1A4931B1D1D8B00EF50C4 /* NSURL.swift */; }; D76C52051ACD46B100B49735 /* JSONHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FAD07691A70F2FC00C4D09E /* JSONHelper.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ @@ -106,6 +110,7 @@ 5F31FF7D1C53499000EF50C4 /* NSDecimalNumberTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSDecimalNumberTests.swift; sourceTree = ""; }; 5F6A2F491CC0116D00EF50C4 /* JSONHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONHelper.swift; sourceTree = ""; }; 5F6A2F4D1CC096DA00EF50C4 /* Serialization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Serialization.swift; sourceTree = ""; }; + 5F6A2F521CC09B9A00EF50C4 /* DeserializableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeserializableTests.swift; sourceTree = ""; }; 5F8F88221CA5F32E00EF50C4 /* DictionaryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DictionaryTests.swift; sourceTree = ""; }; 5F8F88241CA5F33500EF50C4 /* EnumTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnumTests.swift; sourceTree = ""; }; 5F928D961C0D469F00EF50C4 /* JSONHelper.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JSONHelper.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -199,6 +204,29 @@ name = Support; sourceTree = ""; }; + 5F6A2F511CC09B6000EF50C4 /* Extension Tests */ = { + isa = PBXGroup; + children = ( + 5F024AE21B412BA900EF50C4 /* BoolTests.swift */, + 5F024AE01B4127C900EF50C4 /* IntTests.swift */, + 5F31FF7B1C53497600EF50C4 /* FloatTests.swift */, + 5F31FF791C53496B00EF50C4 /* DoubleTests.swift */, + 5F31FF7D1C53499000EF50C4 /* NSDecimalNumberTests.swift */, + 5FB9D4DF1B38007C00EF50C4 /* StringTests.swift */, + 5F31FF6B1C533F1600EF50C4 /* ColorTests.swift */, + 5F31FF551C5339B900EF50C4 /* NSDateTests.swift */, + 5F31FF571C5339CE00EF50C4 /* NSURLTests.swift */, + ); + name = "Extension Tests"; + sourceTree = ""; + }; + 5F6A2F541CC09BB500EF50C4 /* Support Tests */ = { + isa = PBXGroup; + children = ( + ); + name = "Support Tests"; + sourceTree = ""; + }; 5F928D9F1C0D478800EF50C4 /* tvOS */ = { isa = PBXGroup; children = ( @@ -260,18 +288,12 @@ isa = PBXGroup; children = ( 5FAD07761A70F2FC00C4D09E /* JSONHelperTests.swift */, - 5F024AE21B412BA900EF50C4 /* BoolTests.swift */, - 5F024AE01B4127C900EF50C4 /* IntTests.swift */, - 5F31FF7B1C53497600EF50C4 /* FloatTests.swift */, - 5F31FF791C53496B00EF50C4 /* DoubleTests.swift */, - 5F31FF7D1C53499000EF50C4 /* NSDecimalNumberTests.swift */, - 5FB9D4DF1B38007C00EF50C4 /* StringTests.swift */, + 5F6A2F511CC09B6000EF50C4 /* Extension Tests */, 5F8F88241CA5F33500EF50C4 /* EnumTests.swift */, - 5F31FF6B1C533F1600EF50C4 /* ColorTests.swift */, - 5F31FF551C5339B900EF50C4 /* NSDateTests.swift */, - 5F31FF571C5339CE00EF50C4 /* NSURLTests.swift */, + 5F6A2F521CC09B9A00EF50C4 /* DeserializableTests.swift */, 5FD3A09F1CA5F5C300EF50C4 /* ArrayTests.swift */, 5F8F88221CA5F32E00EF50C4 /* DictionaryTests.swift */, + 5F6A2F541CC09BB500EF50C4 /* Support Tests */, ); path = JSONHelperTests; sourceTree = ""; @@ -541,17 +563,20 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 5F31FF691C533EAA00EF50C4 /* String.swift in Sources */, - 5F31FF701C5348F000EF50C4 /* NSDecimalNumber.swift in Sources */, + 5FDBD5221CC46C2A00EF50C4 /* NSURL.swift in Sources */, 5F31FF641C533E9D00EF50C4 /* Deserialization.swift in Sources */, - 5F31FF6A1C533EAD00EF50C4 /* Int.swift in Sources */, + 5FDBD51F1CC46C2A00EF50C4 /* String.swift in Sources */, 5F31FF661C533EA100EF50C4 /* Conversion.swift in Sources */, - 5F31FF781C53490B00EF50C4 /* Float.swift in Sources */, 5F133DA41C3840CA00EF50C4 /* JSONAPI.swift in Sources */, - 5F31FF741C5348FE00EF50C4 /* Double.swift in Sources */, - 5F31FF621C533E9900EF50C4 /* Color.swift in Sources */, + 5FDBD51B1CC46C2A00EF50C4 /* Int.swift in Sources */, + 5FDBD5201CC46C2A00EF50C4 /* Color.swift in Sources */, + 5FDBD51C1CC46C2A00EF50C4 /* Float.swift in Sources */, + 5FDBD51E1CC46C2A00EF50C4 /* NSDecimalNumber.swift in Sources */, 5F6A2F501CC096DA00EF50C4 /* Serialization.swift in Sources */, 5F6A2F4C1CC0116D00EF50C4 /* JSONHelper.swift in Sources */, + 5FDBD5211CC46C2A00EF50C4 /* NSDate.swift in Sources */, + 5FDBD51D1CC46C2A00EF50C4 /* Double.swift in Sources */, + 5FDBD51A1CC46C2A00EF50C4 /* Bool.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -581,6 +606,7 @@ buildActionMask = 2147483647; files = ( 5F024AE11B4127C900EF50C4 /* IntTests.swift in Sources */, + 5F6A2F531CC09B9A00EF50C4 /* DeserializableTests.swift in Sources */, 5F024AE31B412BA900EF50C4 /* BoolTests.swift in Sources */, 5F31FF7A1C53496B00EF50C4 /* DoubleTests.swift in Sources */, 5F31FF7E1C53499000EF50C4 /* NSDecimalNumberTests.swift in Sources */, diff --git a/JSONHelper/Conversion.swift b/JSONHelper/Conversion.swift index fa367bc..92ec022 100644 --- a/JSONHelper/Conversion.swift +++ b/JSONHelper/Conversion.swift @@ -26,6 +26,18 @@ public protocol Convertible { // MARK: - Basic Conversion +public func <-- (inout lhs: T?, rhs: U?) throws -> T? { + lhs = rhs as? T + return lhs +} + +public func <-- (inout lhs: T, rhs: U?) throws -> T { + var newValue: T? + try newValue <-- rhs + lhs = newValue ?? lhs + return lhs +} + public func <-- (inout lhs: C?, rhs: T?) throws -> C? { lhs = try C.convertFromValue(JSONHelper.convertToNilIfNull(rhs)) return lhs diff --git a/JSONHelper/Extensions/Color.swift b/JSONHelper/Extensions/Color.swift index 049c4ee..748a4b1 100644 --- a/JSONHelper/Extensions/Color.swift +++ b/JSONHelper/Extensions/Color.swift @@ -52,6 +52,8 @@ import AppKit extension NSColor: Convertible { public static func convertFromValue(value: T?) throws -> Self? { + guard let value = value else { return nil } + if let stringValue = value as? String { let rgba = try ColorConversionHelper.hexStringToRGBA(stringValue) return self.init(red: rgba.red, green: rgba.green, blue: rgba.blue, alpha: rgba.alpha) @@ -68,6 +70,8 @@ import UIKit extension UIColor: Convertible { public static func convertFromValue(value: T?) throws -> Self? { + guard let value = value else { return nil } + if let stringValue = value as? String { let rgba = try ColorConversionHelper.hexStringToRGBA(stringValue) return self.init(red: rgba.red, green: rgba.green, blue: rgba.blue, alpha: rgba.alpha) diff --git a/JSONHelper/Extensions/NSURL.swift b/JSONHelper/Extensions/NSURL.swift index 2d083ad..55c5c91 100644 --- a/JSONHelper/Extensions/NSURL.swift +++ b/JSONHelper/Extensions/NSURL.swift @@ -7,7 +7,11 @@ import Foundation extension NSURL: Convertible { public static func convertFromValue(value: T?) throws -> Self? { - if let stringValue = value as? String { + guard let value = value else { return nil } + + if let urlValue = value as? NSURL { + return self.init(string: urlValue.absoluteString) + } else if let stringValue = value as? String { return self.init(string: stringValue) } diff --git a/JSONHelper/Support/JSONAPI.swift b/JSONHelper/Support/JSONAPI.swift index 6d9b3f9..884cecb 100644 --- a/JSONHelper/Support/JSONAPI.swift +++ b/JSONHelper/Support/JSONAPI.swift @@ -20,14 +20,14 @@ // case jsonapi, links, data, included, errors, meta // } // -// public init(jsonObject: [String : AnyObject]) { -// jsonapi <-- jsonObject[Fields.jsonapi.rawValue] -// links <-- jsonObject[Fields.links.rawValue] -// self.data = jsonObject[Fields.data.rawValue] -// included <-- jsonObject[Fields.included.rawValue] -// errors <-- jsonObject[Fields.errors.rawValue] -// meta <-- jsonObject[Fields.meta.rawValue] -// raw = jsonObject +// public init(dictionary: [String : AnyObject]) throws { +// try jsonapi <-- dictionary[Fields.jsonapi.rawValue] +// try links <-- dictionary[Fields.links.rawValue] +// self.data = dictionary[Fields.data.rawValue] +// try included <-- dictionary[Fields.included.rawValue] +// try errors <-- dictionary[Fields.errors.rawValue] +// try meta <-- dictionary[Fields.meta.rawValue] +// raw = dictionary // } // // public init() { @@ -39,9 +39,9 @@ // /// // /// This is an expensive operation and should only be used if needed. // public mutating func replaceRelationshipsInDataWithIncluded() { -// if let dataDictionary = jsonObject as? [String : AnyObject] { +// if let dataDictionary = data as? [String : AnyObject] { // data = processDataDictionary(dataDictionary) -// } else if let dataArray = jsonObject as? [[String : AnyObject]] { +// } else if let dataArray = data as? [[String : AnyObject]] { // var newData = [[String : AnyObject]]() // for dataDictionary in dataArray { // newData.append(processDataDictionary(dataDictionary)) @@ -51,18 +51,18 @@ // } // // private func processDataDictionary(dataDictionary: [String : AnyObject]) -> [String : AnyObject] { -// let resourceObject = JSONAPIResourceObject(data: dataDictionary) +// let resourceObject = (try? JSONAPIResourceObject(dictionary: dataDictionary)) ?? JSONAPIResourceObject() // var newData = [String : AnyObject]() // // for (key, value) in dataDictionary { -// newjsonObject[key] = value +// newData[key] = value // } // // var newRelationships = [String: [String : AnyObject]]() // for (relationshipName, relationshipObject) in resourceObject.relationships { // var newRelationship = [String : AnyObject]() // -// if let links = jsonObjectDictionary["relationships"]?[relationshipName]?["links"] { +// if let links = dataDictionary["relationships"]?[relationshipName]??["links"] { // newRelationship["links"] = links // } // @@ -77,14 +77,14 @@ // newRelationship["data"] = newRelationshipData // } // -// if let meta = jsonObjectDictionary["relationships"]?[relationshipName]?["meta"] { +// if let meta = dataDictionary["relationships"]?[relationshipName]??["meta"] { // newRelationship["meta"] = meta // } // // newRelationships[relationshipName] = newRelationship // } // -// newjsonObject["relationships"] = newRelationships +// newData["relationships"] = newRelationships // // return newData // } @@ -122,8 +122,8 @@ // case version // } // -// public init(jsonObject: [String : AnyObject]) { -// version <-- jsonObject[Field.version.rawValue] +// public init(dictionary: [String : AnyObject]) throws { +// try version <-- dictionary[Field.version.rawValue] // } // // public init() {} @@ -149,21 +149,25 @@ // case next = "next" // } // -// public init(jsonObject: [String : AnyObject]) { -// current = deserializeLink(jsonObject[Field.current.rawValue]) -// about = deserializeLink(jsonObject[Field.about.rawValue]) -// related = deserializeLink(jsonObject[Field.related.rawValue]) -// first = deserializeLink(jsonObject[Field.first.rawValue]) -// last = deserializeLink(jsonObject[Field.last.rawValue]) -// prev = deserializeLink(jsonObject[Field.prev.rawValue]) -// next = deserializeLink(jsonObject[Field.next.rawValue]) +// public init(dictionary: [String : AnyObject]) { +// current = deserializeLink(dictionary[Field.current.rawValue]) +// about = deserializeLink(dictionary[Field.about.rawValue]) +// related = deserializeLink(dictionary[Field.related.rawValue]) +// first = deserializeLink(dictionary[Field.first.rawValue]) +// last = deserializeLink(dictionary[Field.last.rawValue]) +// prev = deserializeLink(dictionary[Field.prev.rawValue]) +// next = deserializeLink(dictionary[Field.next.rawValue]) // } // // private func deserializeLink(data: AnyObject?) -> JSONAPILink? { -// if let urlString = jsonObject as? String { -// return JSONAPILink(data: [JSONAPILink.Field.href.rawValue: urlString]) +// do { +// if let urlString = data as? String { +// return try JSONAPILink(dictionary: [JSONAPILink.Field.href.rawValue: urlString]) +// } +// return try JSONAPILink(dictionary: (data as? [String : AnyObject]) ?? [:]) +// } catch { +// return nil // } -// return JSONAPILink(data: (data as? [String : AnyObject]) ?? [:]) // } // // public init() {} @@ -178,9 +182,9 @@ // case href, meta // } // -// public init(jsonObject: [String : AnyObject]) { -// href <-- jsonObject[Field.href.rawValue] -// meta <-- jsonObject[Field.meta.rawValue] +// public init(dictionary: [String : AnyObject]) throws { +// try href <-- dictionary[Field.href.rawValue] +// try meta <-- dictionary[Field.meta.rawValue] // } //} // @@ -199,15 +203,15 @@ // case id, links, status, code, title, detail, source, meta // } // -// public init(jsonObject: [String : AnyObject]) { -// id <-- jsonObject[Field.id.rawValue] -// links <-- jsonObject[Field.links.rawValue] -// status <-- jsonObject[Field.status.rawValue] -// code <-- jsonObject[Field.code.rawValue] -// title <-- jsonObject[Field.title.rawValue] -// detail <-- jsonObject[Field.detail.rawValue] -// source <-- jsonObject[Field.source.rawValue] -// meta <-- jsonObject[Field.meta.rawValue] +// public init(dictionary: [String : AnyObject]) throws { +// try id <-- dictionary[Field.id.rawValue] +// try links <-- dictionary[Field.links.rawValue] +// try status <-- dictionary[Field.status.rawValue] +// try code <-- dictionary[Field.code.rawValue] +// try title <-- dictionary[Field.title.rawValue] +// try detail <-- dictionary[Field.detail.rawValue] +// try source <-- dictionary[Field.source.rawValue] +// try meta <-- dictionary[Field.meta.rawValue] // } //} // @@ -220,17 +224,16 @@ // case pointer, parameter // } // -// public init(jsonObject: [String : AnyObject]) { -// pointer <-- jsonObject[Field.pointer.rawValue] -// parameter <-- jsonObject[Field.parameter.rawValue] +// public init(dictionary: [String : AnyObject]) throws { +// try pointer <-- dictionary[Field.pointer.rawValue] +// try parameter <-- dictionary[Field.parameter.rawValue] // } // // public init() {} //} // ///// A JSON API resource object. http://jsonapi.org/format/#document-resource-objects -//public class JSONAPIResourceObject: NSObject, NSCoding, Deserializable { -// private(set) public var jsonRepresentation = [String : AnyObject]() +//public struct JSONAPIResourceObject: Deserializable, Serializable { // private(set) public var id: String? // private(set) public var type: String? // private(set) public var attributes = [String : AnyObject]() @@ -242,36 +245,32 @@ // case id, type, attributes, relationships, links // } // -// public required init(jsonObject: [String : AnyObject]) { -// super.init() -// update(jsonObject) +// public init(dictionary: [String : AnyObject]) throws { +// try id <-- (dictionary[BaseFields.id.rawValue] ?? id) +// try type <-- (dictionary[BaseFields.type.rawValue] ?? type) +// try attributes <-- dictionary[BaseFields.attributes.rawValue] +// try relationships <-- dictionary[BaseFields.relationships.rawValue] +// try links <-- dictionary[BaseFields.links.rawValue] // } // -// public override init() { -// super.init() -// } +// public init() {} // -// public required init?(coder aDecoder: NSCoder) { -// super.init() -// update(aDecoder.decodeObjectForKeyAs("jsonRepresentation") ?? [:]) -// } +// public func toDictionary() -> [String : AnyObject] { +// var dictionary = [String : AnyObject]() // -// public func update(data: [String : AnyObject]) { -// jsonRepresentation += jsonObject -// id <-- (jsonObject[BaseFields.id.rawValue] ?? id) -// type <-- (jsonObject[BaseFields.type.rawValue] ?? type) -// attributes <-- jsonObject[BaseFields.attributes.rawValue] -// relationships <-- jsonObject[BaseFields.relationships.rawValue] -// links <-- jsonObject[BaseFields.links.rawValue] -// } +// dictionary[BaseFields.id.rawValue] = id +// dictionary[BaseFields.type.rawValue] = type +// dictionary[BaseFields.attributes.rawValue] = attributes +// +// // TODO: relationships +// +// // TODO: links // -// public func encodeWithCoder(aCoder: NSCoder) { -// // TODO: Update jsonRepresentation, use reflection. -// aCoder.encodeObject(jsonRepresentation, forKey: "jsonRepresentation") +// return dictionary // } // -// public override var description: String { -// return jsonRepresentation.description +// public var description: String { +// return toDictionary().description // } //} // @@ -285,9 +284,9 @@ // case links, data, meta // } // -// public init(jsonObject: [String : AnyObject]) { -// links <-- jsonObject[Field.links.rawValue] -// self.data = jsonObject[Field.data.rawValue] -// meta <-- jsonObject[Field.meta.rawValue] +// public init(dictionary: [String : AnyObject]) throws { +// try links <-- dictionary[Field.links.rawValue] +// self.data = dictionary[Field.data.rawValue] +// try meta <-- dictionary[Field.meta.rawValue] // } //} diff --git a/JSONHelperTests/DeserializableTests.swift b/JSONHelperTests/DeserializableTests.swift new file mode 100644 index 0000000..31c9c50 --- /dev/null +++ b/JSONHelperTests/DeserializableTests.swift @@ -0,0 +1,41 @@ +// +// Copyright © 2016 Baris Sencan. All rights reserved. +// + +import Foundation +import XCTest +import JSONHelper + +class DeserializableTests: XCTestCase { + + struct Item: Deserializable { + static let nameKey = "name" + + var name = "" + + init(dictionary: [String : AnyObject]) throws { + try name <-- dictionary[Item.nameKey] + } + + init() {} + } + + let itemDictionary = [Item.nameKey : "a"] + let itemString = "{ \"name\": \"a\" }" + + var item = Item() + + override func setUp() { + item = Item() + } + + func testDictionaryDeserialization() { + try! item <-- itemDictionary + XCTAssertEqual(item.name, itemDictionary[Item.nameKey]) + } + + func testStringDeserialization() { + try! item <-- itemString + XCTAssertEqual(item.name, itemDictionary[Item.nameKey]) + } +} diff --git a/JSONHelperTests/JSONHelperTests.swift b/JSONHelperTests/JSONHelperTests.swift index 05d1e08..fa5d4c9 100644 --- a/JSONHelperTests/JSONHelperTests.swift +++ b/JSONHelperTests/JSONHelperTests.swift @@ -1,9 +1,5 @@ // -// JSONHelperTests.swift -// JSONHelperTests -// -// Created by Baris Sencan on 28/08/14. -// Copyright (c) 2014 Baris Sencan. All rights reserved. +// Copyright © 2016 Baris Sencan. All rights reserved. // import UIKit @@ -11,127 +7,17 @@ import XCTest import JSONHelper class JSONHelperTests: XCTestCase { - let dummyResponse: [String : AnyObject] = [ - "date": "2014-09-19", - "url": "http://github.com/", - "stringArray": ["a", "b", "c"], - "intArray": [1, 2, 3, 4, 5], - "boolArray": [true, false], - "instance": [ - "name": "b" - ], - "instanceArray": [ - [ - "name": "c" - ], [ - "name": "d" - ] - ], - "instanceMap": [ - "ePerson": [ - "name": "e" - ], - "fPerson": [ - "name": "f" - ] - ] - ] - struct Person: Deserializable { - var name = "" + func testConvertToNilIfNull() { + let nilValues: [AnyObject?] = [NSNull(), nil] + let nonNilValues = [0, "", false, [], [:]] - init(dictionary: [String : AnyObject]) { - try! name <-- dictionary["name"] + for nilValue in nilValues { + XCTAssert(JSONHelper.convertToNilIfNull(nilValue) == nil) } - init() {} - } - - enum EnumTest: Int { - case Zero = 0 - case One = 1 + for nonNilValue in nonNilValues { + XCTAssert(JSONHelper.convertToNilIfNull(nonNilValue) != nil) + } } - -// -// func testInstance() { -// var instance = Person() -// instance <-- dummyResponse["instance"] -// XCTAssertEqual(instance.name, "b", "Person instance's name property should equal 'b'") -// } -// -// func testInstanceArray() { -// var property = [Person]() -// property <-- dummyResponse["instanceArray"] -// XCTAssertEqual(property.count, 2, "[Person] property should have 2 members") -// } -// -// func testJSONStringToInstance() { -// let name = "Bob" -// var person: Person? -// person <-- "{\"name\": \"\(name)\"}" -// XCTAssert(person?.name == name, "Person instance's name property should equal '\(name)'") -// } -// -// func testJSONStringToInstanceArray() { -// let jsonString = "[{\"name\": \"I am \"},{\"name\": \"Groot!\"}]" -// var people = [Person]() -// people <-- jsonString -// var areYouGroot = "" -// for person in people { -// areYouGroot += person.name -// } -// XCTAssertEqual(areYouGroot, "I am Groot!", "Groot should be Groot") -// } -// -// func testInstanceMap() { -// var property = [String:Person]() -// property <-- dummyResponse["instanceMap"] -// XCTAssertEqual(property["ePerson"]!.name, "e", "member \"ePerson\" of [String:Person] property should have \"e\" for name") -// } -// -// func testRawValueEnum() { -// var property = EnumTest.Zero -// property <-- dummyResponse["int"] -// XCTAssertEqual(property, EnumTest.One, "EnumTest should be equal to .One") -// } -// -// func testJSONStringMapParsing() { -// var jsonString = "{\"person one\": {\"name\": \"I am \"}, \"person two\": {\"name\": \"Groot!\"}}" -// var jsonObject: JSONObject? = JSONStringToJSONObject(jsonString) -// var people = [String:Person]() -// var areYouGroot = "" -// var keys = "" -// -// people <-- jsonObject -// -// for (personKey, person) in people { -// areYouGroot += person.name -// keys += personKey -// } -// -// XCTAssertEqual(keys, "person oneperson two", "keys should be correctly picked up") -// XCTAssertEqual(areYouGroot, "I am Groot!", "Groot should be Groot") -// } -// -// func testJSONIntObjectMap() { -// var jsonString = "{\"1\": {\"name\": \"Grace\"}, \"2\": {\"name\": \"Lancy\"}}" -// var jsonObject: JSONObject? = JSONStringToJSONObject(jsonString) -// var people = [Int: Person]() -// -// people <-- jsonObject -// -// XCTAssertEqual(people[1]!.name, "Grace", "people[1] should be Grace") -// XCTAssertEqual(people[2]!.name, "Lancy", "people[2] should be Lancy") -// } -// -// func testJSONIntIntMap() { -// var jsonString = "{\"1\": 1, \"2\": 2}" -// var jsonObject: JSONObject? = JSONStringToJSONObject(jsonString) -// var dict = [Int: Int]() -// -// dict <-- jsonObject -// -// XCTAssertEqual(dict[1]!, 1, "dict[1] should be 1") -// XCTAssertEqual(dict[2]!, 2, "dict[2] should be 2") -// } } diff --git a/JSONHelperTests/NSURLTests.swift b/JSONHelperTests/NSURLTests.swift index fa4bd6d..0cfac35 100644 --- a/JSONHelperTests/NSURLTests.swift +++ b/JSONHelperTests/NSURLTests.swift @@ -16,7 +16,7 @@ class NSURLTests: XCTestCase { func testStringConversion() { var url = NSURL() - try! url <-- urlString + try! url <-- (urlString as Any) XCTAssertEqual(url.host, urlHost) } }