From c76c8bb6e6b0e97892dc33247362f9c77b22fce0 Mon Sep 17 00:00:00 2001 From: Matthew Cheok Date: Thu, 15 Oct 2015 22:15:18 -0700 Subject: [PATCH 1/4] Added enumeration support and refactor Moved utility methods to helper classes --- Demo/Demo.xcodeproj/project.pbxproj | 516 ------------------ .../contents.xcworkspacedata | 7 - Demo/Demo/AppDelegate.swift | 46 -- .../AppIcon.appiconset/Contents.json | 38 -- Demo/Demo/Base.lproj/LaunchScreen.storyboard | 27 - Demo/Demo/Base.lproj/Main.storyboard | 40 -- Demo/Demo/Company.swift | 35 -- Demo/Demo/Info.plist | 40 -- Demo/Demo/User.swift | 50 -- Demo/Demo/ViewController.swift | 67 --- Demo/DemoTests/DemoTests.swift | 36 -- Demo/DemoTests/Info.plist | 24 - Demo/DemoUITests/DemoUITests.swift | 34 -- Demo/DemoUITests/Info.plist | 24 - JSONCodable.playground/Contents.swift | 2 +- JSONCodable.playground/contents.xcplayground | 2 +- JSONCodable.xcodeproj/project.pbxproj | 341 +++++++----- .../contents.xcworkspacedata | 3 - JSONCodable/JSONDecodable.swift | 242 ++++---- JSONCodable/JSONEncodable.swift | 234 +++++--- JSONCodable/JSONHelpers.swift | 14 +- JSONCodableTests/Company.swift | 34 ++ JSONCodableTests/EnumTests.swift | 39 ++ JSONCodableTests/Fruit.swift | 44 ++ ...ONCodableTests.swift => HelperTests.swift} | 26 +- JSONCodableTests/ImageAsset.swift | 41 ++ JSONCodableTests/RegularTests.swift | 54 ++ JSONCodableTests/TransformerTests.swift | 40 ++ JSONCodableTests/User.swift | 54 ++ 29 files changed, 820 insertions(+), 1334 deletions(-) delete mode 100644 Demo/Demo.xcodeproj/project.pbxproj delete mode 100644 Demo/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 Demo/Demo/AppDelegate.swift delete mode 100644 Demo/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Demo/Demo/Base.lproj/LaunchScreen.storyboard delete mode 100644 Demo/Demo/Base.lproj/Main.storyboard delete mode 100644 Demo/Demo/Company.swift delete mode 100644 Demo/Demo/Info.plist delete mode 100644 Demo/Demo/User.swift delete mode 100644 Demo/Demo/ViewController.swift delete mode 100644 Demo/DemoTests/DemoTests.swift delete mode 100644 Demo/DemoTests/Info.plist delete mode 100644 Demo/DemoUITests/DemoUITests.swift delete mode 100644 Demo/DemoUITests/Info.plist create mode 100644 JSONCodableTests/Company.swift create mode 100644 JSONCodableTests/EnumTests.swift create mode 100644 JSONCodableTests/Fruit.swift rename JSONCodableTests/{JSONCodableTests.swift => HelperTests.swift} (55%) create mode 100644 JSONCodableTests/ImageAsset.swift create mode 100644 JSONCodableTests/RegularTests.swift create mode 100644 JSONCodableTests/TransformerTests.swift create mode 100644 JSONCodableTests/User.swift diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj deleted file mode 100644 index 58c9b2e..0000000 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ /dev/null @@ -1,516 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 9ED87ACB1B5A493A001CA154 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ED87ACA1B5A493A001CA154 /* AppDelegate.swift */; }; - 9ED87ACD1B5A493A001CA154 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ED87ACC1B5A493A001CA154 /* ViewController.swift */; }; - 9ED87AD01B5A493A001CA154 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9ED87ACE1B5A493A001CA154 /* Main.storyboard */; }; - 9ED87AD21B5A493A001CA154 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9ED87AD11B5A493A001CA154 /* Assets.xcassets */; }; - 9ED87AD51B5A493A001CA154 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9ED87AD31B5A493A001CA154 /* LaunchScreen.storyboard */; }; - 9ED87AE01B5A493A001CA154 /* DemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ED87ADF1B5A493A001CA154 /* DemoTests.swift */; }; - 9ED87AEB1B5A493A001CA154 /* DemoUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ED87AEA1B5A493A001CA154 /* DemoUITests.swift */; }; - 9ED87AF91B5A4A22001CA154 /* JSONCodable.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9ED87AF81B5A4A22001CA154 /* JSONCodable.framework */; }; - 9ED87AFB1B5A4A6B001CA154 /* Company.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ED87AFA1B5A4A6B001CA154 /* Company.swift */; }; - 9ED87AFD1B5A4B24001CA154 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ED87AFC1B5A4B24001CA154 /* User.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 9ED87ADC1B5A493A001CA154 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 9ED87ABF1B5A493A001CA154 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 9ED87AC61B5A493A001CA154; - remoteInfo = Demo; - }; - 9ED87AE71B5A493A001CA154 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 9ED87ABF1B5A493A001CA154 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 9ED87AC61B5A493A001CA154; - remoteInfo = Demo; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 9ED87AC71B5A493A001CA154 /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 9ED87ACA1B5A493A001CA154 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 9ED87ACC1B5A493A001CA154 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 9ED87ACF1B5A493A001CA154 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 9ED87AD11B5A493A001CA154 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 9ED87AD41B5A493A001CA154 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 9ED87AD61B5A493A001CA154 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 9ED87ADB1B5A493A001CA154 /* DemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 9ED87ADF1B5A493A001CA154 /* DemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoTests.swift; sourceTree = ""; }; - 9ED87AE11B5A493A001CA154 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 9ED87AE61B5A493A001CA154 /* DemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 9ED87AEA1B5A493A001CA154 /* DemoUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoUITests.swift; sourceTree = ""; }; - 9ED87AEC1B5A493A001CA154 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 9ED87AF81B5A4A22001CA154 /* JSONCodable.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = JSONCodable.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 9ED87AFA1B5A4A6B001CA154 /* Company.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Company.swift; sourceTree = ""; }; - 9ED87AFC1B5A4B24001CA154 /* User.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 9ED87AC41B5A493A001CA154 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 9ED87AF91B5A4A22001CA154 /* JSONCodable.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9ED87AD81B5A493A001CA154 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9ED87AE31B5A493A001CA154 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 9ED87ABE1B5A493A001CA154 = { - isa = PBXGroup; - children = ( - 9ED87AF81B5A4A22001CA154 /* JSONCodable.framework */, - 9ED87AC91B5A493A001CA154 /* Demo */, - 9ED87ADE1B5A493A001CA154 /* DemoTests */, - 9ED87AE91B5A493A001CA154 /* DemoUITests */, - 9ED87AC81B5A493A001CA154 /* Products */, - ); - sourceTree = ""; - }; - 9ED87AC81B5A493A001CA154 /* Products */ = { - isa = PBXGroup; - children = ( - 9ED87AC71B5A493A001CA154 /* Demo.app */, - 9ED87ADB1B5A493A001CA154 /* DemoTests.xctest */, - 9ED87AE61B5A493A001CA154 /* DemoUITests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 9ED87AC91B5A493A001CA154 /* Demo */ = { - isa = PBXGroup; - children = ( - 9ED87ACA1B5A493A001CA154 /* AppDelegate.swift */, - 9ED87AFC1B5A4B24001CA154 /* User.swift */, - 9ED87AFA1B5A4A6B001CA154 /* Company.swift */, - 9ED87ACC1B5A493A001CA154 /* ViewController.swift */, - 9ED87ACE1B5A493A001CA154 /* Main.storyboard */, - 9ED87AD11B5A493A001CA154 /* Assets.xcassets */, - 9ED87AD31B5A493A001CA154 /* LaunchScreen.storyboard */, - 9ED87AD61B5A493A001CA154 /* Info.plist */, - ); - path = Demo; - sourceTree = ""; - }; - 9ED87ADE1B5A493A001CA154 /* DemoTests */ = { - isa = PBXGroup; - children = ( - 9ED87ADF1B5A493A001CA154 /* DemoTests.swift */, - 9ED87AE11B5A493A001CA154 /* Info.plist */, - ); - path = DemoTests; - sourceTree = ""; - }; - 9ED87AE91B5A493A001CA154 /* DemoUITests */ = { - isa = PBXGroup; - children = ( - 9ED87AEA1B5A493A001CA154 /* DemoUITests.swift */, - 9ED87AEC1B5A493A001CA154 /* Info.plist */, - ); - path = DemoUITests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 9ED87AC61B5A493A001CA154 /* Demo */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9ED87AEF1B5A493A001CA154 /* Build configuration list for PBXNativeTarget "Demo" */; - buildPhases = ( - 9ED87AC31B5A493A001CA154 /* Sources */, - 9ED87AC41B5A493A001CA154 /* Frameworks */, - 9ED87AC51B5A493A001CA154 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Demo; - productName = Demo; - productReference = 9ED87AC71B5A493A001CA154 /* Demo.app */; - productType = "com.apple.product-type.application"; - }; - 9ED87ADA1B5A493A001CA154 /* DemoTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9ED87AF21B5A493A001CA154 /* Build configuration list for PBXNativeTarget "DemoTests" */; - buildPhases = ( - 9ED87AD71B5A493A001CA154 /* Sources */, - 9ED87AD81B5A493A001CA154 /* Frameworks */, - 9ED87AD91B5A493A001CA154 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 9ED87ADD1B5A493A001CA154 /* PBXTargetDependency */, - ); - name = DemoTests; - productName = DemoTests; - productReference = 9ED87ADB1B5A493A001CA154 /* DemoTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 9ED87AE51B5A493A001CA154 /* DemoUITests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9ED87AF51B5A493A001CA154 /* Build configuration list for PBXNativeTarget "DemoUITests" */; - buildPhases = ( - 9ED87AE21B5A493A001CA154 /* Sources */, - 9ED87AE31B5A493A001CA154 /* Frameworks */, - 9ED87AE41B5A493A001CA154 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 9ED87AE81B5A493A001CA154 /* PBXTargetDependency */, - ); - name = DemoUITests; - productName = DemoUITests; - productReference = 9ED87AE61B5A493A001CA154 /* DemoUITests.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 9ED87ABF1B5A493A001CA154 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0700; - ORGANIZATIONNAME = matthewcheok; - TargetAttributes = { - 9ED87AC61B5A493A001CA154 = { - CreatedOnToolsVersion = 7.0; - }; - 9ED87ADA1B5A493A001CA154 = { - CreatedOnToolsVersion = 7.0; - TestTargetID = 9ED87AC61B5A493A001CA154; - }; - 9ED87AE51B5A493A001CA154 = { - CreatedOnToolsVersion = 7.0; - TestTargetID = 9ED87AC61B5A493A001CA154; - }; - }; - }; - buildConfigurationList = 9ED87AC21B5A493A001CA154 /* Build configuration list for PBXProject "Demo" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 9ED87ABE1B5A493A001CA154; - productRefGroup = 9ED87AC81B5A493A001CA154 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 9ED87AC61B5A493A001CA154 /* Demo */, - 9ED87ADA1B5A493A001CA154 /* DemoTests */, - 9ED87AE51B5A493A001CA154 /* DemoUITests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 9ED87AC51B5A493A001CA154 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 9ED87AD51B5A493A001CA154 /* LaunchScreen.storyboard in Resources */, - 9ED87AD21B5A493A001CA154 /* Assets.xcassets in Resources */, - 9ED87AD01B5A493A001CA154 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9ED87AD91B5A493A001CA154 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9ED87AE41B5A493A001CA154 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 9ED87AC31B5A493A001CA154 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 9ED87AFD1B5A4B24001CA154 /* User.swift in Sources */, - 9ED87ACD1B5A493A001CA154 /* ViewController.swift in Sources */, - 9ED87ACB1B5A493A001CA154 /* AppDelegate.swift in Sources */, - 9ED87AFB1B5A4A6B001CA154 /* Company.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9ED87AD71B5A493A001CA154 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 9ED87AE01B5A493A001CA154 /* DemoTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9ED87AE21B5A493A001CA154 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 9ED87AEB1B5A493A001CA154 /* DemoUITests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 9ED87ADD1B5A493A001CA154 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 9ED87AC61B5A493A001CA154 /* Demo */; - targetProxy = 9ED87ADC1B5A493A001CA154 /* PBXContainerItemProxy */; - }; - 9ED87AE81B5A493A001CA154 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 9ED87AC61B5A493A001CA154 /* Demo */; - targetProxy = 9ED87AE71B5A493A001CA154 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 9ED87ACE1B5A493A001CA154 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 9ED87ACF1B5A493A001CA154 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 9ED87AD31B5A493A001CA154 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 9ED87AD41B5A493A001CA154 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 9ED87AED1B5A493A001CA154 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 9ED87AEE1B5A493A001CA154 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 9ED87AF01B5A493A001CA154 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = Demo/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.Demo; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 9ED87AF11B5A493A001CA154 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = Demo/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.Demo; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 9ED87AF31B5A493A001CA154 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - INFOPLIST_FILE = DemoTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.DemoTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Demo.app/Demo"; - }; - name = Debug; - }; - 9ED87AF41B5A493A001CA154 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - INFOPLIST_FILE = DemoTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.DemoTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Demo.app/Demo"; - }; - name = Release; - }; - 9ED87AF61B5A493A001CA154 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - INFOPLIST_FILE = DemoUITests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.DemoUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_TARGET_NAME = Demo; - USES_XCTRUNNER = YES; - }; - name = Debug; - }; - 9ED87AF71B5A493A001CA154 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - INFOPLIST_FILE = DemoUITests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.DemoUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_TARGET_NAME = Demo; - USES_XCTRUNNER = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 9ED87AC21B5A493A001CA154 /* Build configuration list for PBXProject "Demo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9ED87AED1B5A493A001CA154 /* Debug */, - 9ED87AEE1B5A493A001CA154 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 9ED87AEF1B5A493A001CA154 /* Build configuration list for PBXNativeTarget "Demo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9ED87AF01B5A493A001CA154 /* Debug */, - 9ED87AF11B5A493A001CA154 /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; - 9ED87AF21B5A493A001CA154 /* Build configuration list for PBXNativeTarget "DemoTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9ED87AF31B5A493A001CA154 /* Debug */, - 9ED87AF41B5A493A001CA154 /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; - 9ED87AF51B5A493A001CA154 /* Build configuration list for PBXNativeTarget "DemoUITests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9ED87AF61B5A493A001CA154 /* Debug */, - 9ED87AF71B5A493A001CA154 /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; -/* End XCConfigurationList section */ - }; - rootObject = 9ED87ABF1B5A493A001CA154 /* Project object */; -} diff --git a/Demo/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Demo/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a..0000000 --- a/Demo/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Demo/Demo/AppDelegate.swift b/Demo/Demo/AppDelegate.swift deleted file mode 100644 index 3047525..0000000 --- a/Demo/Demo/AppDelegate.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// AppDelegate.swift -// Demo -// -// Created by Matthew Cheok on 18/7/15. -// Copyright © 2015 matthewcheok. All rights reserved. -// - -import UIKit - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { - // Override point for customization after application launch. - return true - } - - func applicationWillResignActive(application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. - } - - func applicationDidEnterBackground(application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - } - - func applicationWillEnterForeground(application: UIApplication) { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. - } - - func applicationDidBecomeActive(application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - } - - func applicationWillTerminate(application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - } - - -} - diff --git a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 118c98f..0000000 --- a/Demo/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Demo/Demo/Base.lproj/LaunchScreen.storyboard b/Demo/Demo/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 2e721e1..0000000 --- a/Demo/Demo/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Demo/Demo/Base.lproj/Main.storyboard b/Demo/Demo/Base.lproj/Main.storyboard deleted file mode 100644 index 700af1e..0000000 --- a/Demo/Demo/Base.lproj/Main.storyboard +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Demo/Demo/Company.swift b/Demo/Demo/Company.swift deleted file mode 100644 index a2c5169..0000000 --- a/Demo/Demo/Company.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// Company.swift -// Demo -// -// Created by Matthew Cheok on 18/7/15. -// Copyright © 2015 matthewcheok. All rights reserved. -// - -import Foundation -import JSONCodable - -struct Company { - let name: String - var address: String? -} - -extension Company: JSONCodable { - init?(JSONDictionary: [String : AnyObject]) { - do { - name = try JSONDictionary.decode("name") - address = try JSONDictionary.decode("address") - } - catch { - print(error) - return nil - } - } - - func toJSON() throws -> AnyObject { - var result = [String: AnyObject]() - try result.encode(name, key: "name") - try result.encode(address, key: "address") - return result - } -} \ No newline at end of file diff --git a/Demo/Demo/Info.plist b/Demo/Demo/Info.plist deleted file mode 100644 index 6905cc6..0000000 --- a/Demo/Demo/Info.plist +++ /dev/null @@ -1,40 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/Demo/Demo/User.swift b/Demo/Demo/User.swift deleted file mode 100644 index 2350c72..0000000 --- a/Demo/Demo/User.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// User.swift -// Demo -// -// Created by Matthew Cheok on 18/7/15. -// Copyright © 2015 matthewcheok. All rights reserved. -// - -import Foundation -import JSONCodable - -struct User { - let id: Int - let name: String - var email: String? - var company: Company? - var friends: [User] = [] - var website: NSURL? - var props: [String: String] = [:] -} - -extension User: JSONCodable { - init?(JSONDictionary: [String : AnyObject]) { - do { - id = try JSONDictionary.decode("id") - name = try JSONDictionary.decode("full_name") - email = try JSONDictionary.decode("email") - company = try JSONDictionary.decode("company") - friends = try JSONDictionary.decode("friends") - website = try JSONDictionary.decode("website.url", transformer: JSONTransformers.StringToNSURL) - props = try JSONDictionary.decode("props") - } - catch { - print(error) - return nil - } - } - - func toJSON() throws -> AnyObject { - var result = [String: AnyObject]() - try result.encode(id, key: "id") - try result.encode(name, key: "full_name") - try result.encode(email, key: "email") - try result.encode(company, key: "company") - try result.encode(friends, key: "friends") - try result.encode(website, key: "website", transformer: JSONTransformers.StringToNSURL) - try result.encode(props, key: "props") - return result - } -} diff --git a/Demo/Demo/ViewController.swift b/Demo/Demo/ViewController.swift deleted file mode 100644 index 884610b..0000000 --- a/Demo/Demo/ViewController.swift +++ /dev/null @@ -1,67 +0,0 @@ -// -// ViewController.swift -// Demo -// -// Created by Matthew Cheok on 18/7/15. -// Copyright © 2015 matthewcheok. All rights reserved. -// - -import UIKit - -class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. - - - let JSON = [ - "id": 24, - "full_name": "John Appleseed", - "email": "john@appleseed.com", - "company": [ - "name": "Apple", - "address": "1 Infinite Loop, Cupertino, CA" - ], - "friends": [ - ["id": 27, "full_name": "Bob Jefferson"], - ["id": 29, "full_name": "Jen Jackson"] - ], - "website": ["url": "http://johnappleseed.com"], - "props": ["prop a": "value a", "prop b": "value b"] - ] - - print("Initial JSON:\n\(JSON)\n\n") - - let user = User(JSONDictionary: JSON)! - - print("Decoded: \n\(user)\n\n") - - do { - let dict = try user.toJSON() - print("Encoded: \n\(dict as! [String: AnyObject])\n\n") - } - catch { - print("Error: \(error)") - } - - //do { - // let string = try user.JSONString() - // print(string) - // - // let userAgain = User(JSONString: string) - // print(userAgain) - //} catch { - // print("Error: \(error)") - //} - - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - -} - diff --git a/Demo/DemoTests/DemoTests.swift b/Demo/DemoTests/DemoTests.swift deleted file mode 100644 index 575da88..0000000 --- a/Demo/DemoTests/DemoTests.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// DemoTests.swift -// DemoTests -// -// Created by Matthew Cheok on 18/7/15. -// Copyright © 2015 matthewcheok. All rights reserved. -// - -import XCTest -@testable import Demo - -class DemoTests: XCTestCase { - - override func setUp() { - super.setUp() - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() - } - - func testExample() { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - } - - func testPerformanceExample() { - // This is an example of a performance test case. - self.measureBlock { - // Put the code you want to measure the time of here. - } - } - -} diff --git a/Demo/DemoTests/Info.plist b/Demo/DemoTests/Info.plist deleted file mode 100644 index ba72822..0000000 --- a/Demo/DemoTests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/Demo/DemoUITests/DemoUITests.swift b/Demo/DemoUITests/DemoUITests.swift deleted file mode 100644 index d77f632..0000000 --- a/Demo/DemoUITests/DemoUITests.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// DemoUITests.swift -// DemoUITests -// -// Created by Matthew Cheok on 18/7/15. -// Copyright © 2015 matthewcheok. All rights reserved. -// - -import XCTest - -class DemoUITests: XCTestCase { - - override func setUp() { - super.setUp() - - // Put setup code here. This method is called before the invocation of each test method in the class. - - // In UI tests it is usually best to stop immediately when a failure occurs. - continueAfterFailure = false - // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. - XCUIApplication().launch() - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() - } - - func testExample() { - // Use recording to get started writing UI tests. - // Use XCTAssert and related functions to verify your tests produce the correct results. - } - -} diff --git a/Demo/DemoUITests/Info.plist b/Demo/DemoUITests/Info.plist deleted file mode 100644 index ba72822..0000000 --- a/Demo/DemoUITests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/JSONCodable.playground/Contents.swift b/JSONCodable.playground/Contents.swift index bc20186..0ca4165 100644 --- a/JSONCodable.playground/Contents.swift +++ b/JSONCodable.playground/Contents.swift @@ -31,7 +31,7 @@ We'll add conformance to `JSONEncodable`. You may also add conformance to `JSONC */ extension User: JSONEncodable { - func JSONEncode() throws -> AnyObject { + func toJSON() throws -> AnyObject { var result = [String: AnyObject]() try result.encode(id, key: "id") try result.encode(name, key: "full_name") diff --git a/JSONCodable.playground/contents.xcplayground b/JSONCodable.playground/contents.xcplayground index af4f38c..0b96219 100644 --- a/JSONCodable.playground/contents.xcplayground +++ b/JSONCodable.playground/contents.xcplayground @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/JSONCodable.xcodeproj/project.pbxproj b/JSONCodable.xcodeproj/project.pbxproj index a045db5..36244b9 100644 --- a/JSONCodable.xcodeproj/project.pbxproj +++ b/JSONCodable.xcodeproj/project.pbxproj @@ -7,6 +7,15 @@ objects = { /* Begin PBXBuildFile section */ + 9E455BFA1BCE185B00070A4F /* EnumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E455BF91BCE185B00070A4F /* EnumTests.swift */; }; + 9E455BFC1BCE185B00070A4F /* JSONCodable.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EDB39231B59D01D00C63019 /* JSONCodable.framework */; settings = {ASSET_TAGS = (); }; }; + 9E455C031BCE1C1E00070A4F /* Fruit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E455C021BCE1C1E00070A4F /* Fruit.swift */; settings = {ASSET_TAGS = (); }; }; + 9E455C051BCE1D0700070A4F /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E455C041BCE1D0700070A4F /* User.swift */; settings = {ASSET_TAGS = (); }; }; + 9E455C091BCE1DE100070A4F /* Company.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E455C081BCE1DE100070A4F /* Company.swift */; settings = {ASSET_TAGS = (); }; }; + 9E455C0B1BCE1F0100070A4F /* RegularTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E455C0A1BCE1F0100070A4F /* RegularTests.swift */; settings = {ASSET_TAGS = (); }; }; + 9ECF00C01BCE251B008D557C /* TransformerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ECF00BF1BCE251B008D557C /* TransformerTests.swift */; settings = {ASSET_TAGS = (); }; }; + 9ECF00C21BCF6E43008D557C /* ImageAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ECF00C11BCF6E43008D557C /* ImageAsset.swift */; settings = {ASSET_TAGS = (); }; }; + 9ECF00C41BCF82F5008D557C /* HelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ECF00C31BCF82F5008D557C /* HelperTests.swift */; settings = {ASSET_TAGS = (); }; }; 9EDB390A1B59D00B00C63019 /* JSONCodable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9EDB39091B59D00B00C63019 /* JSONCodable.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9EDB39431B59D0AF00C63019 /* JSONCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EDB393C1B59D0AF00C63019 /* JSONCodable.swift */; }; 9EDB39441B59D0AF00C63019 /* JSONCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EDB393C1B59D0AF00C63019 /* JSONCodable.swift */; }; @@ -21,21 +30,29 @@ 9EDB394F1B59D0AF00C63019 /* JSONTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EDB39421B59D0AF00C63019 /* JSONTransformer.swift */; }; 9EDB39501B59D0AF00C63019 /* JSONTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EDB39421B59D0AF00C63019 /* JSONTransformer.swift */; }; 9EDB39511B59D15400C63019 /* JSONCodable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9EDB39091B59D00B00C63019 /* JSONCodable.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DD9AF0A61BCE79AE00AD42D1 /* JSONCodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9AF0A51BCE79AE00AD42D1 /* JSONCodableTests.swift */; }; - DD9AF0A81BCE79AE00AD42D1 /* JSONCodable.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EDB39061B59D00B00C63019 /* JSONCodable.framework */; settings = {ASSET_TAGS = (); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - DD9AF0A91BCE79AE00AD42D1 /* PBXContainerItemProxy */ = { + 9E455BFD1BCE185B00070A4F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 9EDF80101B59CFCE00E4A2D6 /* Project object */; proxyType = 1; - remoteGlobalIDString = 9EDB39051B59D00B00C63019; - remoteInfo = "JSONCodable iOS"; + remoteGlobalIDString = 9EDB39221B59D01D00C63019; + remoteInfo = "JSONCodable OSX"; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 9E455BF71BCE185B00070A4F /* JSONCodableTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JSONCodableTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 9E455BF91BCE185B00070A4F /* EnumTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnumTests.swift; sourceTree = ""; }; + 9E455BFB1BCE185B00070A4F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9E455C021BCE1C1E00070A4F /* Fruit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fruit.swift; sourceTree = ""; }; + 9E455C041BCE1D0700070A4F /* User.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; + 9E455C081BCE1DE100070A4F /* Company.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Company.swift; sourceTree = ""; }; + 9E455C0A1BCE1F0100070A4F /* RegularTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegularTests.swift; sourceTree = ""; }; + 9ECF00BF1BCE251B008D557C /* TransformerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransformerTests.swift; sourceTree = ""; }; + 9ECF00C11BCF6E43008D557C /* ImageAsset.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageAsset.swift; sourceTree = ""; }; + 9ECF00C31BCF82F5008D557C /* HelperTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HelperTests.swift; sourceTree = ""; }; 9EDB39061B59D00B00C63019 /* JSONCodable.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JSONCodable.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9EDB39091B59D00B00C63019 /* JSONCodable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSONCodable.h; sourceTree = ""; }; 9EDB390B1B59D00B00C63019 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -46,43 +63,72 @@ 9EDB393F1B59D0AF00C63019 /* JSONHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONHelpers.swift; sourceTree = ""; }; 9EDB39411B59D0AF00C63019 /* JSONString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONString.swift; sourceTree = ""; }; 9EDB39421B59D0AF00C63019 /* JSONTransformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONTransformer.swift; sourceTree = ""; }; - DD9AF0A31BCE79AE00AD42D1 /* JSONCodableTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JSONCodableTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - DD9AF0A51BCE79AE00AD42D1 /* JSONCodableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONCodableTests.swift; sourceTree = ""; }; - DD9AF0A71BCE79AE00AD42D1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 9EDB39021B59D00B00C63019 /* Frameworks */ = { + 9E455BF41BCE185B00070A4F /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9E455BFC1BCE185B00070A4F /* JSONCodable.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 9EDB391F1B59D01D00C63019 /* Frameworks */ = { + 9EDB39021B59D00B00C63019 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - DD9AF0A01BCE79AE00AD42D1 /* Frameworks */ = { + 9EDB391F1B59D01D00C63019 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DD9AF0A81BCE79AE00AD42D1 /* JSONCodable.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 9E455BF81BCE185B00070A4F /* JSONCodableTests */ = { + isa = PBXGroup; + children = ( + 9E455C061BCE1D0B00070A4F /* Models */, + 9E455C071BCE1D1900070A4F /* Tests */, + 9E455BFB1BCE185B00070A4F /* Info.plist */, + ); + path = JSONCodableTests; + sourceTree = ""; + }; + 9E455C061BCE1D0B00070A4F /* Models */ = { + isa = PBXGroup; + children = ( + 9E455C021BCE1C1E00070A4F /* Fruit.swift */, + 9E455C041BCE1D0700070A4F /* User.swift */, + 9E455C081BCE1DE100070A4F /* Company.swift */, + 9ECF00C11BCF6E43008D557C /* ImageAsset.swift */, + ); + name = Models; + sourceTree = ""; + }; + 9E455C071BCE1D1900070A4F /* Tests */ = { + isa = PBXGroup; + children = ( + 9ECF00C31BCF82F5008D557C /* HelperTests.swift */, + 9E455C0A1BCE1F0100070A4F /* RegularTests.swift */, + 9E455BF91BCE185B00070A4F /* EnumTests.swift */, + 9ECF00BF1BCE251B008D557C /* TransformerTests.swift */, + ); + name = Tests; + sourceTree = ""; + }; 9EDB39071B59D00B00C63019 /* Products */ = { isa = PBXGroup; children = ( 9EDB39061B59D00B00C63019 /* JSONCodable.framework */, 9EDB39231B59D01D00C63019 /* JSONCodable.framework */, - DD9AF0A31BCE79AE00AD42D1 /* JSONCodableTests.xctest */, + 9E455BF71BCE185B00070A4F /* JSONCodableTests.xctest */, ); name = Products; sourceTree = ""; @@ -114,20 +160,11 @@ children = ( 9EDB393B1B59D0AF00C63019 /* JSONCodable */, 9EDB39081B59D00B00C63019 /* Supporting Files */, - DD9AF0A41BCE79AE00AD42D1 /* JSONCodableTests */, + 9E455BF81BCE185B00070A4F /* JSONCodableTests */, 9EDB39071B59D00B00C63019 /* Products */, ); sourceTree = ""; }; - DD9AF0A41BCE79AE00AD42D1 /* JSONCodableTests */ = { - isa = PBXGroup; - children = ( - DD9AF0A51BCE79AE00AD42D1 /* JSONCodableTests.swift */, - DD9AF0A71BCE79AE00AD42D1 /* Info.plist */, - ); - path = JSONCodableTests; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -150,6 +187,24 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 9E455BF61BCE185B00070A4F /* JSONCodableTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9E455C011BCE185B00070A4F /* Build configuration list for PBXNativeTarget "JSONCodableTests" */; + buildPhases = ( + 9E455BF31BCE185B00070A4F /* Sources */, + 9E455BF41BCE185B00070A4F /* Frameworks */, + 9E455BF51BCE185B00070A4F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 9E455BFE1BCE185B00070A4F /* PBXTargetDependency */, + ); + name = JSONCodableTests; + productName = JSONCodableTests; + productReference = 9E455BF71BCE185B00070A4F /* JSONCodableTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 9EDB39051B59D00B00C63019 /* JSONCodable iOS */ = { isa = PBXNativeTarget; buildConfigurationList = 9EDB391C1B59D00B00C63019 /* Build configuration list for PBXNativeTarget "JSONCodable iOS" */; @@ -186,24 +241,6 @@ productReference = 9EDB39231B59D01D00C63019 /* JSONCodable.framework */; productType = "com.apple.product-type.framework"; }; - DD9AF0A21BCE79AE00AD42D1 /* JSONCodableTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = DD9AF0AB1BCE79AE00AD42D1 /* Build configuration list for PBXNativeTarget "JSONCodableTests" */; - buildPhases = ( - DD9AF09F1BCE79AE00AD42D1 /* Sources */, - DD9AF0A01BCE79AE00AD42D1 /* Frameworks */, - DD9AF0A11BCE79AE00AD42D1 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - DD9AF0AA1BCE79AE00AD42D1 /* PBXTargetDependency */, - ); - name = JSONCodableTests; - productName = JSONCodableTests; - productReference = DD9AF0A31BCE79AE00AD42D1 /* JSONCodableTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -211,17 +248,16 @@ isa = PBXProject; attributes = { LastUpgradeCheck = 0700; - ORGANIZATIONNAME = matthewcheok; TargetAttributes = { + 9E455BF61BCE185B00070A4F = { + CreatedOnToolsVersion = 7.0.1; + }; 9EDB39051B59D00B00C63019 = { CreatedOnToolsVersion = 7.0; }; 9EDB39221B59D01D00C63019 = { CreatedOnToolsVersion = 7.0; }; - DD9AF0A21BCE79AE00AD42D1 = { - CreatedOnToolsVersion = 7.0.1; - }; }; }; buildConfigurationList = 9EDF80131B59CFCE00E4A2D6 /* Build configuration list for PBXProject "JSONCodable" */; @@ -238,27 +274,27 @@ targets = ( 9EDB39051B59D00B00C63019 /* JSONCodable iOS */, 9EDB39221B59D01D00C63019 /* JSONCodable OSX */, - DD9AF0A21BCE79AE00AD42D1 /* JSONCodableTests */, + 9E455BF61BCE185B00070A4F /* JSONCodableTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 9EDB39041B59D00B00C63019 /* Resources */ = { + 9E455BF51BCE185B00070A4F /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 9EDB39211B59D01D00C63019 /* Resources */ = { + 9EDB39041B59D00B00C63019 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - DD9AF0A11BCE79AE00AD42D1 /* Resources */ = { + 9EDB39211B59D01D00C63019 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -268,6 +304,21 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 9E455BF31BCE185B00070A4F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9ECF00C41BCF82F5008D557C /* HelperTests.swift in Sources */, + 9ECF00C21BCF6E43008D557C /* ImageAsset.swift in Sources */, + 9E455C031BCE1C1E00070A4F /* Fruit.swift in Sources */, + 9ECF00C01BCE251B008D557C /* TransformerTests.swift in Sources */, + 9E455BFA1BCE185B00070A4F /* EnumTests.swift in Sources */, + 9E455C0B1BCE1F0100070A4F /* RegularTests.swift in Sources */, + 9E455C051BCE1D0700070A4F /* User.swift in Sources */, + 9E455C091BCE1DE100070A4F /* Company.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 9EDB39011B59D00B00C63019 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -294,26 +345,18 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - DD9AF09F1BCE79AE00AD42D1 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DD9AF0A61BCE79AE00AD42D1 /* JSONCodableTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - DD9AF0AA1BCE79AE00AD42D1 /* PBXTargetDependency */ = { + 9E455BFE1BCE185B00070A4F /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 9EDB39051B59D00B00C63019 /* JSONCodable iOS */; - targetProxy = DD9AF0A91BCE79AE00AD42D1 /* PBXContainerItemProxy */; + target = 9EDB39221B59D01D00C63019 /* JSONCodable OSX */; + targetProxy = 9E455BFD1BCE185B00070A4F /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 9EDB39181B59D00B00C63019 /* Debug */ = { + 9E455BFF1BCE185B00070A4F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -330,14 +373,9 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -354,24 +392,19 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + INFOPLIST_FILE = JSONCodableTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.JSONCodable; - PRODUCT_NAME = JSONCodable; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.JSONCodableTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; }; name = Debug; }; - 9EDB39191B59D00B00C63019 /* Release */ = { + 9E455C001BCE185B00070A4F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -388,14 +421,9 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -406,23 +434,17 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + INFOPLIST_FILE = JSONCodableTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.JSONCodable; - PRODUCT_NAME = JSONCodable; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; + PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.JSONCodableTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; }; name = Release; }; - 9EDB39351B59D01D00C63019 /* Debug */ = { + 9EDB39181B59D00B00C63019 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -439,7 +461,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; @@ -449,7 +471,6 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - FRAMEWORK_VERSION = A; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -466,21 +487,22 @@ GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.10; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.JSONCodable; PRODUCT_NAME = JSONCodable; - SDKROOT = macosx; + SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; - 9EDB39361B59D01D00C63019 /* Release */ = { + 9EDB39191B59D00B00C63019 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -497,7 +519,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -507,7 +529,6 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_VERSION = A; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -518,35 +539,21 @@ GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.10; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.JSONCodable; PRODUCT_NAME = JSONCodable; - SDKROOT = macosx; + SDKROOT = iphoneos; SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; - 9EDF80141B59CFCE00E4A2D6 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MACOSX_DEPLOYMENT_TARGET = 10.10; - }; - name = Debug; - }; - 9EDF80151B59CFCE00E4A2D6 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MACOSX_DEPLOYMENT_TARGET = 10.10; - }; - name = Release; - }; - DD9AF0AC1BCE79AE00AD42D1 /* Debug */ = { + 9EDB39351B59D01D00C63019 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -563,10 +570,17 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + FRAMEWORK_VERSION = A; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -581,19 +595,23 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = JSONCodableTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.JSONCodableTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; + PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.JSONCodable; + PRODUCT_NAME = JSONCodable; + SDKROOT = macosx; + SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Debug; }; - DD9AF0AD1BCE79AE00AD42D1 /* Release */ = { + 9EDB39361B59D01D00C63019 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -610,10 +628,17 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_VERSION = A; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -622,20 +647,48 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = JSONCodableTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.JSONCodableTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.matthewcheok.JSONCodable; + PRODUCT_NAME = JSONCodable; + SDKROOT = macosx; + SKIP_INSTALL = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 9EDF80141B59CFCE00E4A2D6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MACOSX_DEPLOYMENT_TARGET = 10.10; + }; + name = Debug; + }; + 9EDF80151B59CFCE00E4A2D6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MACOSX_DEPLOYMENT_TARGET = 10.10; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 9E455C011BCE185B00070A4F /* Build configuration list for PBXNativeTarget "JSONCodableTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9E455BFF1BCE185B00070A4F /* Debug */, + 9E455C001BCE185B00070A4F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 9EDB391C1B59D00B00C63019 /* Build configuration list for PBXNativeTarget "JSONCodable iOS" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -663,14 +716,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - DD9AF0AB1BCE79AE00AD42D1 /* Build configuration list for PBXNativeTarget "JSONCodableTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DD9AF0AC1BCE79AE00AD42D1 /* Debug */, - DD9AF0AD1BCE79AE00AD42D1 /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; /* End XCConfigurationList section */ }; rootObject = 9EDF80101B59CFCE00E4A2D6 /* Project object */; diff --git a/JSONCodable.xcworkspace/contents.xcworkspacedata b/JSONCodable.xcworkspace/contents.xcworkspacedata index 80fff3c..2e20fba 100644 --- a/JSONCodable.xcworkspace/contents.xcworkspacedata +++ b/JSONCodable.xcworkspace/contents.xcworkspacedata @@ -1,9 +1,6 @@ - - diff --git a/JSONCodable/JSONDecodable.swift b/JSONCodable/JSONDecodable.swift index 5699fd9..8dfdb8f 100644 --- a/JSONCodable/JSONDecodable.swift +++ b/JSONCodable/JSONDecodable.swift @@ -6,7 +6,7 @@ // Copyright © 2015 matthewcheok. All rights reserved. // -// error type +// Decoding Errors public enum JSONDecodableError: ErrorType, CustomStringConvertible { case MissingTypeError( @@ -48,7 +48,7 @@ public enum JSONDecodableError: ErrorType, CustomStringConvertible { // Dictionary -> Struct public protocol JSONDecodable { - init?(JSONDictionary: [String : AnyObject]) + init?(JSONDictionary: JSONObject) } public extension Array where Element: JSONDecodable { @@ -62,16 +62,19 @@ public extension Array where Element: JSONDecodable { } } -// Dictionary convenience methods +// JSONDecoder - provides utility methods for decoding -public extension Dictionary where Value: AnyObject { - private func get(key: Key) -> AnyObject? { - guard let keyString = key as? String else { - return nil - } - let keys = keyString.componentsSeparatedByString(".") +public class JSONDecoder { + let object: JSONObject + + public init(object: JSONObject) { + self.object = object + } + + private func get(key: String) -> AnyObject? { + let keys = key.componentsSeparatedByString(".") - return keys.reduce(self as? AnyObject) { + let result = keys.reduce(object as AnyObject?) { value, key in guard let dict = value as? [String: AnyObject] else { @@ -80,146 +83,169 @@ public extension Dictionary where Value: AnyObject { return dict[key] } + return (result ?? object[key]).flatMap{$0 is NSNull ? nil : $0} } - // optional array of scalars - public func decode(key: Key) throws -> [String: Value]? { - if let y = get(key) ?? self[key] { - guard let x = y as? [String: Value] else { - throw JSONDecodableError.IncompatibleTypeError(key: key as! String, elementType: y.dynamicType, expectedType: [String: Value].self) - } - return x + // JSONCompatible + public func decode(key: String) throws -> Compatible { + guard let value = get(key) else { + throw JSONDecodableError.MissingTypeError(key: key) + } + guard let compatible = value as? Compatible else { + throw JSONDecodableError.IncompatibleTypeError(key: key, elementType: value.dynamicType, expectedType: Compatible.self) } - return nil + return compatible } - // required dictionary of scalars - public func decode(key: Key) throws -> [String: Value] { - guard let y = get(key) ?? self[key] else { - throw JSONDecodableError.MissingTypeError(key: key as! String) + // JSONCompatible? + public func decode(key: String) throws -> Compatible? { + return (get(key) ?? object[key]) as? Compatible + } + + // JSONDecodable + public func decode(key: String) throws -> Decodable { + guard let value = get(key) else { + throw JSONDecodableError.MissingTypeError(key: key) + } + guard let object = value as? JSONObject else { + throw JSONDecodableError.DictionaryTypeExpectedError(key: key, elementType: value.dynamicType) } - guard let x = y as? [String: Value] else { - throw JSONDecodableError.IncompatibleTypeError(key: key as! String, elementType: y.dynamicType, expectedType: [String: Value].self) + guard let decodable = Decodable(JSONDictionary: object) else { + throw JSONDecodableError.IncompatibleTypeError(key: key, elementType: value.dynamicType, expectedType: Decodable.self) } - return x + return decodable } - // TODO: validate array elements - // optional array of decodables - public func decode(key: Key) throws -> [Element]? { - if let y = get(key) ?? self[key] { - guard let x = y as? [[String : AnyObject]] else { - throw JSONDecodableError.ArrayTypeExpectedError(key: key as! String, elementType: y.dynamicType) - } - return x.flatMap {Element(JSONDictionary: $0)} + // JSONDecodable? + public func decode(key: String) throws -> Decodable? { + guard let value = get(key) else { + return nil + } + guard let object = value as? JSONObject else { + throw JSONDecodableError.DictionaryTypeExpectedError(key: key, elementType: value.dynamicType) } - return nil + return Decodable(JSONDictionary: object) } - // required array of decodables - public func decode(key: Key) throws -> [Element] { - guard let y = get(key) ?? self[key] else { - return [] + // Enum + public func decode(key: String) throws -> Enum { + guard let value = get(key) else { + throw JSONDecodableError.MissingTypeError(key: key) + } + guard let raw = value as? Enum.RawValue else { + throw JSONDecodableError.IncompatibleTypeError(key: key, elementType: value.dynamicType, expectedType: Enum.RawValue.self) } - guard let x = y as? [[String : AnyObject]] else { - throw JSONDecodableError.ArrayTypeExpectedError(key: key as! String, elementType: y.dynamicType) + guard let result = Enum(rawValue: raw) else { + throw JSONDecodableError.IncompatibleTypeError(key: key, elementType: Enum.RawValue.self, expectedType: Enum.self) } - return x.flatMap {Element(JSONDictionary: $0)} + return result } - // optional array of scalars - public func decode(key: Key) throws -> [Element]? { - if let y = get(key) ?? self[key] { - guard let x = y as? [Element] else { - throw JSONDecodableError.IncompatibleTypeError(key: key as! String, elementType: y.dynamicType, expectedType: [Element].self) - } - return x + // Enum? + public func decode(key: String) throws -> Enum? { + guard let value = get(key) else { + return nil + } + guard let raw = value as? Enum.RawValue else { + throw JSONDecodableError.IncompatibleTypeError(key: key, elementType: value.dynamicType, expectedType: Enum.RawValue.self) } - return nil + guard let result = Enum(rawValue: raw) else { + throw JSONDecodableError.IncompatibleTypeError(key: key, elementType: Enum.RawValue.self, expectedType: Enum.self) + } + return result } - // required array of scalars - public func decode(key: Key) throws -> [Element] { - guard let y = get(key) ?? self[key] else { - throw JSONDecodableError.MissingTypeError(key: key as! String) + // [JSONCompatible] + public func decode(key: String) throws -> [Element] { + guard let value = get(key) else { + throw JSONDecodableError.MissingTypeError(key: key) } - guard let x = y as? [Element] else { - throw JSONDecodableError.IncompatibleTypeError(key: key as! String, elementType: y.dynamicType, expectedType: [Element].self) + guard let array = value as? [Element] else { + throw JSONDecodableError.IncompatibleTypeError(key: key, elementType: value.dynamicType, expectedType: [Element].self) } - return x + return array } - // optional decodable - public func decode(key: Key) throws -> Type? { - if let y = get(key) ?? self[key] { - if y is NSNull { - return nil - } - guard let x = y as? [String : AnyObject] else { - throw JSONDecodableError.DictionaryTypeExpectedError(key: key as! String, elementType: y.dynamicType) - } - return Type(JSONDictionary: x) + // [JSONCompatible]? + public func decode(key: String) throws -> [Element]? { + guard let value = get(key) else { + return nil } - return nil + guard let array = value as? [Element] else { + throw JSONDecodableError.IncompatibleTypeError(key: key, elementType: value.dynamicType, expectedType: [Element].self) + } + return array } - // required decodable - public func decode(key: Key) throws -> Type { - guard let y = get(key) ?? self[key] else { - throw JSONDecodableError.MissingTypeError(key: key as! String) + // [JSONDecodable] + public func decode(key: String) throws -> [Element] { + guard let value = get(key) else { + return [] } - guard let x = y as? [String : AnyObject] else { - throw JSONDecodableError.DictionaryTypeExpectedError(key: key as! String, elementType: y.dynamicType) + guard let array = value as? [JSONObject] else { + throw JSONDecodableError.ArrayTypeExpectedError(key: key, elementType: value.dynamicType) } - guard let value = Type(JSONDictionary: x) else { - throw JSONDecodableError.IncompatibleTypeError(key: key as! String, elementType: y.dynamicType, expectedType: Type.self) + return array.flatMap {Element(JSONDictionary: $0)} + } + + // [JSONDecodable]? + public func decode(key: String) throws -> [Element]? { + guard let value = get(key) else { + return nil } - return value + guard let array = value as? [JSONObject] else { + throw JSONDecodableError.ArrayTypeExpectedError(key: key, elementType: value.dynamicType) + } + return array.flatMap {Element(JSONDictionary: $0)} } - // optional scalar - public func decode(key: Key) throws -> Type? { - return (get(key) ?? self[key]) as? Type + // [String:JSONCompatible] + public func decode(key: String) throws -> [String: Value] { + guard let value = get(key) else { + throw JSONDecodableError.MissingTypeError(key: key) + } + guard let dictionary = value as? [String: Value] else { + throw JSONDecodableError.IncompatibleTypeError(key: key, elementType: value.dynamicType, expectedType: [String: Value].self) + } + return dictionary } - // required scalar - public func decode(key: Key) throws -> Type { - guard let y = get(key) ?? self[key] else { - throw JSONDecodableError.MissingTypeError(key: key as! String) + // [String:JSONCompatible]? + public func decode(key: String) throws -> [String: Value]? { + guard let value = get(key) else { + return nil } - guard let x = y as? Type else { - throw JSONDecodableError.IncompatibleTypeError(key: key as! String, elementType: y.dynamicType, expectedType: Type.self) + guard let dictionary = value as? [String: Value] else { + throw JSONDecodableError.IncompatibleTypeError(key: key, elementType: value.dynamicType, expectedType: [String: Value].self) } - return x + return dictionary } - // optional transformable - public func decode(key: Key, transformer: JSONTransformer) throws -> DecodedType? { - if let y = get(key) ?? self[key] { - guard let x = y as? EncodedType else { - throw JSONDecodableError.IncompatibleTypeError(key: key as! String, elementType: y.dynamicType, expectedType: EncodedType.self) - } - guard let z = transformer.decoding(x) else { - throw JSONDecodableError.TransformerFailedError(key: key as! String) - } - - return z + // JSONTransformable + public func decode(key: String, transformer: JSONTransformer) throws -> DecodedType { + guard let value = get(key) else { + throw JSONDecodableError.MissingTypeError(key: key) } - return nil + guard let actual = value as? EncodedType else { + throw JSONDecodableError.IncompatibleTypeError(key: key, elementType: value.dynamicType, expectedType: EncodedType.self) + } + guard let result = transformer.decoding(actual) else { + throw JSONDecodableError.TransformerFailedError(key: key) + } + return result } - // required transformable - public func decode(key: Key, transformer: JSONTransformer) throws -> DecodedType { - guard let y = get(key) ?? self[key] else { - throw JSONDecodableError.MissingTypeError(key: key as! String) + // JSONTransformable? + public func decode(key: String, transformer: JSONTransformer) throws -> DecodedType? { + guard let value = get(key) else { + return nil } - guard let x = y as? EncodedType else { - throw JSONDecodableError.IncompatibleTypeError(key: key as! String, elementType: y.dynamicType, expectedType: EncodedType.self) + guard let actual = value as? EncodedType else { + throw JSONDecodableError.IncompatibleTypeError(key: key, elementType: value.dynamicType, expectedType: EncodedType.self) } - guard let z = transformer.decoding(x) else { - throw JSONDecodableError.TransformerFailedError(key: key as! String) + guard let result = transformer.decoding(actual) else { + throw JSONDecodableError.TransformerFailedError(key: key) } - - return z + return result } } \ No newline at end of file diff --git a/JSONCodable/JSONEncodable.swift b/JSONCodable/JSONEncodable.swift index 9f8e1e7..fbddf81 100644 --- a/JSONCodable/JSONEncodable.swift +++ b/JSONCodable/JSONEncodable.swift @@ -6,13 +6,22 @@ // Copyright © 2015 matthewcheok. All rights reserved. // -// Error type +// Encoding Errors public enum JSONEncodableError: ErrorType, CustomStringConvertible { - case IncompatibleTypeError(elementType: Any.Type) - case ArrayIncompatibleTypeError(elementType: Any.Type) - case DictionaryIncompatibleTypeError(elementType: Any.Type) - case ChildIncompatibleTypeError(key: String, elementType: Any.Type) + case IncompatibleTypeError( + elementType: Any.Type + ) + case ArrayIncompatibleTypeError( + elementType: Any.Type + ) + case DictionaryIncompatibleTypeError( + elementType: Any.Type + ) + case ChildIncompatibleTypeError( + key: String, + elementType: Any.Type + ) case TransformerFailedError( key: String ) @@ -47,17 +56,38 @@ public extension JSONEncodable { throw JSONEncodableError.IncompatibleTypeError(elementType: self.dynamicType) } - // loop through all properties (instance variables) - var result: [String: AnyObject] = [:] - for (labelMaybe, valueMaybe) in mirror.children { - guard let label = labelMaybe else { - continue + return try JSONEncoder.create({ (encoder) -> Void in + // loop through all properties (instance variables) + for (labelMaybe, valueMaybe) in mirror.children { + guard let label = labelMaybe else { + continue + } + + let value: Any + + // unwrap optionals + if let v = valueMaybe as? JSONOptional { + guard let unwrapped = v.wrapped else { + continue + } + value = unwrapped + } + else { + value = valueMaybe + } + + switch (value) { + case let value as JSONEncodable: + try encoder.encode(value, key: label) + case let value as JSONArray: + try encoder.encode(value, key: label) + case let value as JSONDictionary: + try encoder.encode(value, key: label) + default: + throw JSONEncodableError.ChildIncompatibleTypeError(key: label, elementType: value.dynamicType) + } } - - try result.encode(valueMaybe, key: label) - } - - return result + }) } } @@ -95,65 +125,139 @@ public extension Dictionary {//where Key: String, Value: JSONEncodable { } } -public extension Dictionary where Value: AnyObject { - public mutating func encode(value: Any, key: Key) throws { - let actualValue: Any - - // unwrap optionals - if let v = value as? JSONOptional { - guard let unwrapped = v.wrapped else { - return - } - actualValue = unwrapped +// JSONEncoder - provides utility methods for encoding + +public class JSONEncoder { + var object = JSONObject() + + public static func create(@noescape setup: (encoder: JSONEncoder) throws -> Void) rethrows -> JSONObject { + let encoder = JSONEncoder() + try setup(encoder: encoder) + return encoder.object + } + + /* + Note: + There is some duplication because methods with generic constraints need to + take a concrete type conforming to the constraint are unable to take a parameter + typed to the protocol. Hence we need non-generic versions so we can cast from + Any to JSONEncodable in the default implementation for toJSON(). + */ + + // JSONEncodable + public func encode(value: Encodable, key: String) throws { + let result = try value.toJSON() + object[key] = result + } + private func encode(value: JSONEncodable, key: String) throws { + let result = try value.toJSON() + object[key] = result + } + + // JSONEncodable? + public func encode(value: Encodable?, key: String) throws { + guard let actual = value else { + return } - else { - actualValue = value + let result = try actual.toJSON() + object[key] = result + } + + // Enum + public func encode(value: Enum, key: String) throws { + guard let compatible = value.rawValue as? JSONCompatible else { + return } - - // test for array - if let array = actualValue as? JSONArray { - if array.count > 0 && array.elementsAreJSONEncodable() { - let encodableArray = array.elementsMadeJSONEncodable() - let result = try encodableArray.toJSON() - self[key] = (result as! Value) - } + let result = try compatible.toJSON() + object[key] = result + } + + // Enum? + public func encode(value: Enum?, key: String) throws { + guard let actual = value else { + return } - - // test for compatible type - else if let compatible = actualValue as? JSONEncodable { - let result = try compatible.toJSON() - self[key] = (result as! Value) - } - - // test for dictionary - else if let dict = actualValue as? JSONDictionary { - if dict.dictionaryIsJSONEncodable() { - let encodableDict = dict.dictionaryMadeJSONEncodable() - let result = try encodableDict.toJSON() - self[key] = (result as! Value) - } + guard let compatible = actual.rawValue as? JSONCompatible else { + return + } + let result = try compatible.toJSON() + object[key] = result + } + + // [JSONEncodable] + public func encode(value: [Encodable], key: String) throws { + guard value.count > 0 else { + return } - - // incompatible type - else { - throw JSONEncodableError.ChildIncompatibleTypeError(key: key as! String, elementType: actualValue.dynamicType) + let result = try value.toJSON() + object[key] = result + } + private func encode(array: JSONArray, key: String) throws { + guard array.count > 0 && array.elementsAreJSONEncodable() else { + return } + let encodable = array.elementsMadeJSONEncodable() + let result = try encodable.toJSON() + object[key] = result } - // optional transformable - public mutating func encode(value: DecodedType?, key: Key, transformer: JSONTransformer) throws { - if let value = value { - let encodedValue = transformer.encoding(value) - try encode(encodedValue, key: key) + // [JSONEncodable]? + public func encode(value: [Encodable]?, key: String) throws { + guard let actual = value else { + return } + guard actual.count > 0 else { + return + } + let result = try actual.toJSON() + object[key] = result } - // required transformable - public mutating func encode(value: DecodedType, key: Key, transformer: JSONTransformer) throws { - guard let encodedValue = transformer.encoding(value) else { - throw JSONEncodableError.TransformerFailedError(key: key as! String) + // [String:JSONEncodable] + public func encode(value: [String:Encodable], key: String) throws { + guard value.count > 0 else { + return } - - try encode(encodedValue, key: key) + let result = try value.toJSON() + object[key] = result + } + private func encode(dictionary: JSONDictionary, key: String) throws { + guard dictionary.count > 0 && dictionary.valuesAreJSONEncodable() else { + return + } + let encodable = dictionary.valuesMadeJSONEncodable() + let result = try encodable.toJSON() + object[key] = result + } + + // [String:JSONEncodable]? + public func encode(value: [String:Encodable]?, key: String) throws { + guard let actual = value else { + return + } + guard actual.count > 0 else { + return + } + let result = try actual.toJSON() + object[key] = result + } + + // JSONTransformable + public func encode(value: DecodedType, key: String, transformer: JSONTransformer) throws { + guard let result = transformer.encoding(value) else { + throw JSONEncodableError.TransformerFailedError(key: key) + } + object[key] = (result as! AnyObject) } -} \ No newline at end of file + + // JSONTransformable? + public func encode(value: DecodedType?, key: String, transformer: JSONTransformer) throws { + guard let actual = value else { + return + } + guard let result = transformer.encoding(actual) else { + return + } + object[key] = (result as! AnyObject) + } +} diff --git a/JSONCodable/JSONHelpers.swift b/JSONCodable/JSONHelpers.swift index 374c0fb..1683d07 100644 --- a/JSONCodable/JSONHelpers.swift +++ b/JSONCodable/JSONHelpers.swift @@ -6,19 +6,24 @@ // Copyright © 2015 matthewcheok. All rights reserved. // +// Convenience + +public typealias JSONObject = [String: AnyObject] + // Dictionary handling protocol JSONDictionary { - func dictionaryIsJSONEncodable() -> Bool - func dictionaryMadeJSONEncodable() -> [String: JSONEncodable] + var count: Int { get } + func valuesAreJSONEncodable() -> Bool + func valuesMadeJSONEncodable() -> [String: JSONEncodable] } extension Dictionary : JSONDictionary { - func dictionaryIsJSONEncodable() -> Bool { + func valuesAreJSONEncodable() -> Bool { return Key.self is String.Type && (Value.self is JSONEncodable.Type || Value.self is JSONEncodable.Protocol) } - func dictionaryMadeJSONEncodable() -> [String: JSONEncodable] { + func valuesMadeJSONEncodable() -> [String: JSONEncodable] { var dict: [String: JSONEncodable] = [:] for (k, v) in self { dict[String(k)] = v as? JSONEncodable @@ -45,7 +50,6 @@ extension Array: JSONArray { } } - // Optional handling protocol JSONOptional { diff --git a/JSONCodableTests/Company.swift b/JSONCodableTests/Company.swift new file mode 100644 index 0000000..bee1b14 --- /dev/null +++ b/JSONCodableTests/Company.swift @@ -0,0 +1,34 @@ +// +// Company.swift +// JSONCodable +// +// Created by Matthew Cheok on 13/10/15. +// +// + +import Foundation +import JSONCodable + +struct Company: Equatable { + let name: String + var address: String? +} + +func ==(lhs: Company, rhs: Company) -> Bool { + return lhs.name == rhs.name && lhs.address == rhs.address +} + +extension Company: JSONEncodable {} + +extension Company: JSONDecodable { + init?(JSONDictionary: JSONObject) { + let decoder = JSONDecoder(object: JSONDictionary) + do { + name = try decoder.decode("name") + address = try decoder.decode("address") + } + catch { + return nil + } + } +} \ No newline at end of file diff --git a/JSONCodableTests/EnumTests.swift b/JSONCodableTests/EnumTests.swift new file mode 100644 index 0000000..572f0b0 --- /dev/null +++ b/JSONCodableTests/EnumTests.swift @@ -0,0 +1,39 @@ +// +// EnumTests.swift +// JSONCodable +// +// Created by Matthew Cheok on 13/10/15. +// +// + +import XCTest + +class EnumTests: XCTestCase { + + let encodedValue = ["name": "apple", "color": "Red"] + let decodedValue = Fruit(name: "apple", color: FruitColor.Red) + + func testDecodingEnum() { + guard let fruit = Fruit(JSONDictionary: encodedValue) else { + XCTFail() + return + } + + XCTAssertEqual(fruit, decodedValue) + } + + func testEncodingEnum() { + guard let json = try? decodedValue.toJSON() else { + XCTFail() + return + } + + guard let castedJSON = json as? [String: String] else { + XCTFail() + return + } + + XCTAssertEqual(castedJSON, encodedValue) + } + +} diff --git a/JSONCodableTests/Fruit.swift b/JSONCodableTests/Fruit.swift new file mode 100644 index 0000000..4e54e7c --- /dev/null +++ b/JSONCodableTests/Fruit.swift @@ -0,0 +1,44 @@ +// +// Fruit.swift +// JSONCodable +// +// Created by Matthew Cheok on 13/10/15. +// +// + +import Foundation +import JSONCodable + +enum FruitColor: String { + case Red + case Blue +} + +struct Fruit: Equatable { + let name: String + let color: FruitColor +} + +func ==(lhs: Fruit, rhs: Fruit) -> Bool { + return lhs.name == rhs.name && lhs.color == rhs.color +} + +extension Fruit: JSONCodable { + init?(JSONDictionary: JSONObject) { + let decoder = JSONDecoder(object: JSONDictionary) + do { + name = try decoder.decode("name") + color = try decoder.decode("color") + } + catch { + return nil + } + } + + func toJSON() throws -> AnyObject { + return try JSONEncoder.create({ (encoder) -> Void in + try encoder.encode(name, key: "name") + try encoder.encode(color, key: "color") + }) + } +} \ No newline at end of file diff --git a/JSONCodableTests/JSONCodableTests.swift b/JSONCodableTests/HelperTests.swift similarity index 55% rename from JSONCodableTests/JSONCodableTests.swift rename to JSONCodableTests/HelperTests.swift index b3d18ae..19bfcd4 100644 --- a/JSONCodableTests/JSONCodableTests.swift +++ b/JSONCodableTests/HelperTests.swift @@ -9,21 +9,11 @@ import XCTest @testable import JSONCodable -class JSONCodableTests: XCTestCase { - - override func setUp() { - super.setUp() - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() - } - - struct NotEncodable { - } +struct NotEncodable { +} +class HelperTests: XCTestCase { + func testArrayElementsAreEncodable() { let intArray:[Int] = [1,2,3] XCTAssert(intArray.elementsAreJSONEncodable(), "Array of type [Int] should be encodable") @@ -37,16 +27,14 @@ class JSONCodableTests: XCTestCase { func testDictionaryIsEncodable() { let intDict:[String:Int] = ["a":1,"b":2,"c":3] - XCTAssert(intDict.dictionaryIsJSONEncodable(), "Dictionary of type [String:Int] should be encodable") + XCTAssert(intDict.valuesAreJSONEncodable(), "Dictionary of type [String:Int] should be encodable") let encodableDict:[String:JSONEncodable] = ["a":1,"b":2,"c":3] - XCTAssert(encodableDict.dictionaryIsJSONEncodable(), "Dictionary of type [String:JSONEncodable] should be encodable") + XCTAssert(encodableDict.valuesAreJSONEncodable(), "Dictionary of type [String:JSONEncodable] should be encodable") let notEncodableDict:[String:NotEncodable] = ["a":NotEncodable()] - XCTAssert(!notEncodableDict.dictionaryIsJSONEncodable(), "Dictionary of type [String:NotEncodable] should not be encodable") + XCTAssert(!notEncodableDict.valuesAreJSONEncodable(), "Dictionary of type [String:NotEncodable] should not be encodable") } - - } diff --git a/JSONCodableTests/ImageAsset.swift b/JSONCodableTests/ImageAsset.swift new file mode 100644 index 0000000..acc04ee --- /dev/null +++ b/JSONCodableTests/ImageAsset.swift @@ -0,0 +1,41 @@ +// +// ImageAsset.swift +// JSONCodable +// +// Created by Matthew Cheok on 14/10/15. +// +// + +import Foundation +import JSONCodable + +struct ImageAsset: Equatable { + let name: String + var uri: NSURL? +} + +func ==(lhs: ImageAsset, rhs: ImageAsset) -> Bool { + return lhs.name == rhs.name && lhs.uri == rhs.uri +} + +extension ImageAsset: JSONEncodable { + func toJSON() throws -> AnyObject { + return try JSONEncoder.create({ (encoder) -> Void in + try encoder.encode(name, key: "name") + try encoder.encode(uri, key: "uri", transformer: JSONTransformers.StringToNSURL) + }) + } +} + +extension ImageAsset: JSONDecodable { + init?(JSONDictionary: JSONObject) { + let decoder = JSONDecoder(object: JSONDictionary) + do { + name = try decoder.decode("name") + uri = try decoder.decode("uri", transformer: JSONTransformers.StringToNSURL) + } + catch { + return nil + } + } +} \ No newline at end of file diff --git a/JSONCodableTests/RegularTests.swift b/JSONCodableTests/RegularTests.swift new file mode 100644 index 0000000..d3884c7 --- /dev/null +++ b/JSONCodableTests/RegularTests.swift @@ -0,0 +1,54 @@ +// +// RegularTests.swift +// JSONCodable +// +// Created by Matthew Cheok on 13/10/15. +// +// + +import XCTest + +class RegularTests: XCTestCase { + + let encodedValue = [ + "id": 24, + "full_name": "John Appleseed", + "email": "john@appleseed.com", + "company": [ + "name": "Apple", + "address": "1 Infinite Loop, Cupertino, CA" + ], + "friends": [ + ["id": 27, "full_name": "Bob Jefferson"], + ["id": 29, "full_name": "Jen Jackson"] + ] + ] + let decodedValue = User( + id: 24, + name: "John Appleseed", + email: "john@appleseed.com", + company: Company(name: "Apple", address: "1 Infinite Loop, Cupertino, CA"), + friends: [ + User(id: 27, name: "Bob Jefferson", email: nil, company: nil, friends: []), + User(id: 29, name: "Jen Jackson", email: nil, company: nil, friends: []) + ]) + + func testDecodingRegular() { + guard let user = User(JSONDictionary: encodedValue) else { + XCTFail() + return + } + + XCTAssertEqual(user, decodedValue) + } + + func testEncodingRegular() { + guard let json = try? decodedValue.toJSON() else { + XCTFail() + return + } + + XCTAssertEqual(json as! [String : NSObject], encodedValue) + } + +} \ No newline at end of file diff --git a/JSONCodableTests/TransformerTests.swift b/JSONCodableTests/TransformerTests.swift new file mode 100644 index 0000000..58ae7e7 --- /dev/null +++ b/JSONCodableTests/TransformerTests.swift @@ -0,0 +1,40 @@ +// +// TransformerTests.swift +// JSONCodable +// +// Created by Matthew Cheok on 13/10/15. +// +// + +import XCTest + +class TransformerTests: XCTestCase { + + let encodedValue = [ + "name": "image-name", + "uri": "http://www.example.com/image.png" + ] + let decodedValue = ImageAsset( + name: "image-name", + uri: NSURL(string: "http://www.example.com/image.png") + ) + + func testDecodingTransformer() { + guard let asset = ImageAsset(JSONDictionary: encodedValue) else { + XCTFail() + return + } + + XCTAssertEqual(asset, decodedValue) + } + + func testEncodingTransformer() { + guard let json = try? decodedValue.toJSON() else { + XCTFail() + return + } + + XCTAssertEqual(json as! [String : NSObject], encodedValue) + } + +} \ No newline at end of file diff --git a/JSONCodableTests/User.swift b/JSONCodableTests/User.swift new file mode 100644 index 0000000..9d4002c --- /dev/null +++ b/JSONCodableTests/User.swift @@ -0,0 +1,54 @@ +// +// User.swift +// JSONCodable +// +// Created by Matthew Cheok on 13/10/15. +// +// + +import Foundation +import JSONCodable + +struct User: Equatable { + let id: Int + let name: String + var email: String? + var company: Company? + var friends: [User] = [] +} + +func ==(lhs: User, rhs: User) -> Bool { + return lhs.id == rhs.id && + lhs.name == rhs.name && + lhs.email == rhs.email && + lhs.company == rhs.company && + lhs.friends == rhs.friends +} + +extension User: JSONEncodable { + func toJSON() throws -> AnyObject { + return try JSONEncoder.create({ (encoder) -> Void in + try encoder.encode(id, key: "id") + try encoder.encode(name, key: "full_name") + try encoder.encode(email, key: "email") + try encoder.encode(company, key: "company") + try encoder.encode(friends, key: "friends") + }) + } +} + +extension User: JSONDecodable { + init?(JSONDictionary: JSONObject) { + let decoder = JSONDecoder(object: JSONDictionary) + do { + id = try decoder.decode("id") + name = try decoder.decode("full_name") + email = try decoder.decode("email") + company = try decoder.decode("company") + friends = try decoder.decode("friends") + } + catch { + return nil + } + } +} \ No newline at end of file From dbf4c751ea8f4dd6fd530e2559fe7bcbe78a4b48 Mon Sep 17 00:00:00 2001 From: Matthew Cheok Date: Sun, 18 Oct 2015 08:35:08 -0700 Subject: [PATCH 2/4] Added support for array of Enum --- JSONCodable.xcodeproj/project.pbxproj | 4 +++ JSONCodable/JSONDecodable.swift | 22 ++++++++++++ JSONCodable/JSONEncodable.swift | 25 +++++++++++++ JSONCodableTests/EnumTests.swift | 17 +++++++++ JSONCodableTests/Food.swift | 52 +++++++++++++++++++++++++++ 5 files changed, 120 insertions(+) create mode 100644 JSONCodableTests/Food.swift diff --git a/JSONCodable.xcodeproj/project.pbxproj b/JSONCodable.xcodeproj/project.pbxproj index 36244b9..a7f43a7 100644 --- a/JSONCodable.xcodeproj/project.pbxproj +++ b/JSONCodable.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 9E455C051BCE1D0700070A4F /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E455C041BCE1D0700070A4F /* User.swift */; settings = {ASSET_TAGS = (); }; }; 9E455C091BCE1DE100070A4F /* Company.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E455C081BCE1DE100070A4F /* Company.swift */; settings = {ASSET_TAGS = (); }; }; 9E455C0B1BCE1F0100070A4F /* RegularTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E455C0A1BCE1F0100070A4F /* RegularTests.swift */; settings = {ASSET_TAGS = (); }; }; + 9E8E07241BD3F15800F98421 /* Food.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E8E07231BD3F15800F98421 /* Food.swift */; settings = {ASSET_TAGS = (); }; }; 9ECF00C01BCE251B008D557C /* TransformerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ECF00BF1BCE251B008D557C /* TransformerTests.swift */; settings = {ASSET_TAGS = (); }; }; 9ECF00C21BCF6E43008D557C /* ImageAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ECF00C11BCF6E43008D557C /* ImageAsset.swift */; settings = {ASSET_TAGS = (); }; }; 9ECF00C41BCF82F5008D557C /* HelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ECF00C31BCF82F5008D557C /* HelperTests.swift */; settings = {ASSET_TAGS = (); }; }; @@ -50,6 +51,7 @@ 9E455C041BCE1D0700070A4F /* User.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; 9E455C081BCE1DE100070A4F /* Company.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Company.swift; sourceTree = ""; }; 9E455C0A1BCE1F0100070A4F /* RegularTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegularTests.swift; sourceTree = ""; }; + 9E8E07231BD3F15800F98421 /* Food.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Food.swift; sourceTree = ""; }; 9ECF00BF1BCE251B008D557C /* TransformerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransformerTests.swift; sourceTree = ""; }; 9ECF00C11BCF6E43008D557C /* ImageAsset.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageAsset.swift; sourceTree = ""; }; 9ECF00C31BCF82F5008D557C /* HelperTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HelperTests.swift; sourceTree = ""; }; @@ -105,6 +107,7 @@ isa = PBXGroup; children = ( 9E455C021BCE1C1E00070A4F /* Fruit.swift */, + 9E8E07231BD3F15800F98421 /* Food.swift */, 9E455C041BCE1D0700070A4F /* User.swift */, 9E455C081BCE1DE100070A4F /* Company.swift */, 9ECF00C11BCF6E43008D557C /* ImageAsset.swift */, @@ -313,6 +316,7 @@ 9E455C031BCE1C1E00070A4F /* Fruit.swift in Sources */, 9ECF00C01BCE251B008D557C /* TransformerTests.swift in Sources */, 9E455BFA1BCE185B00070A4F /* EnumTests.swift in Sources */, + 9E8E07241BD3F15800F98421 /* Food.swift in Sources */, 9E455C0B1BCE1F0100070A4F /* RegularTests.swift in Sources */, 9E455C051BCE1D0700070A4F /* User.swift in Sources */, 9E455C091BCE1DE100070A4F /* Company.swift in Sources */, diff --git a/JSONCodable/JSONDecodable.swift b/JSONCodable/JSONDecodable.swift index 8dfdb8f..2045322 100644 --- a/JSONCodable/JSONDecodable.swift +++ b/JSONCodable/JSONDecodable.swift @@ -199,6 +199,28 @@ public class JSONDecoder { return array.flatMap {Element(JSONDictionary: $0)} } + // [Enum] + public func decode(key: String) throws -> [Enum] { + guard let value = get(key) else { + return [] + } + guard let array = value as? [Enum.RawValue] else { + throw JSONDecodableError.ArrayTypeExpectedError(key: key, elementType: value.dynamicType) + } + return array.flatMap { Enum(rawValue: $0) } + } + + // [Enum]? + public func decode(key: String) throws -> [Enum]? { + guard let value = get(key) else { + return nil + } + guard let array = value as? [Enum.RawValue] else { + throw JSONDecodableError.ArrayTypeExpectedError(key: key, elementType: value.dynamicType) + } + return array.flatMap { Enum(rawValue: $0) } + } + // [String:JSONCompatible] public func decode(key: String) throws -> [String: Value] { guard let value = get(key) else { diff --git a/JSONCodable/JSONEncodable.swift b/JSONCodable/JSONEncodable.swift index fbddf81..baa5f9c 100644 --- a/JSONCodable/JSONEncodable.swift +++ b/JSONCodable/JSONEncodable.swift @@ -213,6 +213,31 @@ public class JSONEncoder { object[key] = result } + // [Enum] + public func encode(value: [Enum], key: String) throws { + guard value.count > 0 else { + return + } + let result = try value.flatMap { + try ($0.rawValue as? JSONCompatible)?.toJSON() + } + object[key] = result + } + + // [Enum]? + public func encode(value: [Enum]?, key: String) throws { + guard let actual = value else { + return + } + guard actual.count > 0 else { + return + } + let result = try actual.flatMap { + try ($0.rawValue as? JSONCompatible)?.toJSON() + } + object[key] = result + } + // [String:JSONEncodable] public func encode(value: [String:Encodable], key: String) throws { guard value.count > 0 else { diff --git a/JSONCodableTests/EnumTests.swift b/JSONCodableTests/EnumTests.swift index 572f0b0..516906a 100644 --- a/JSONCodableTests/EnumTests.swift +++ b/JSONCodableTests/EnumTests.swift @@ -13,6 +13,9 @@ class EnumTests: XCTestCase { let encodedValue = ["name": "apple", "color": "Red"] let decodedValue = Fruit(name: "apple", color: FruitColor.Red) + let encodedValue2 = ["name": "Seaweed Pasta", "cuisines": ["Italian", "Japanese"]] + let decodedValue2 = Food(name: "Seaweed Pasta", cuisines: [.Italian, .Japanese]) + func testDecodingEnum() { guard let fruit = Fruit(JSONDictionary: encodedValue) else { XCTFail() @@ -20,6 +23,13 @@ class EnumTests: XCTestCase { } XCTAssertEqual(fruit, decodedValue) + + guard let food = Food(JSONDictionary: encodedValue2) else { + XCTFail() + return + } + + XCTAssertEqual(food, decodedValue2) } func testEncodingEnum() { @@ -34,6 +44,13 @@ class EnumTests: XCTestCase { } XCTAssertEqual(castedJSON, encodedValue) + + guard let json2 = try? decodedValue2.toJSON() else { + XCTFail() + return + } + + print(json2, encodedValue2) } } diff --git a/JSONCodableTests/Food.swift b/JSONCodableTests/Food.swift new file mode 100644 index 0000000..06f88e9 --- /dev/null +++ b/JSONCodableTests/Food.swift @@ -0,0 +1,52 @@ +// +// Food.swift +// JSONCodable +// +// Created by Matthew Cheok on 18/10/15. +// +// + +import Foundation +import JSONCodable + +enum Cuisine: String { + case Mexican + case Italian + case German + case French + case Pizza + case Barbecue + case Chinese + case Japanese + case Korean + case Thai +} + +struct Food: Equatable { + let name: String + let cuisines: [Cuisine] +} + +func ==(lhs: Food, rhs: Food) -> Bool { + return lhs.name == rhs.name && lhs.cuisines == rhs.cuisines +} + +extension Food: JSONCodable { + init?(JSONDictionary: JSONObject) { + let decoder = JSONDecoder(object: JSONDictionary) + do { + name = try decoder.decode("name") + cuisines = try decoder.decode("cuisines") + } + catch { + return nil + } + } + + func toJSON() throws -> AnyObject { + return try JSONEncoder.create({ (encoder) -> Void in + try encoder.encode(name, key: "name") + try encoder.encode(cuisines, key: "cuisines") + }) + } +} \ No newline at end of file From 21082ae9426282ea1fb2c67106bf951bd394bf9f Mon Sep 17 00:00:00 2001 From: Matthew Cheok Date: Sun, 18 Oct 2015 08:53:55 -0700 Subject: [PATCH 3/4] Updated documentation --- JSONCodable.playground/Contents.swift | 42 +++++++++++----------- README.md | 52 ++++++++++++++------------- 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/JSONCodable.playground/Contents.swift b/JSONCodable.playground/Contents.swift index 0ca4165..10e14c7 100644 --- a/JSONCodable.playground/Contents.swift +++ b/JSONCodable.playground/Contents.swift @@ -32,20 +32,20 @@ We'll add conformance to `JSONEncodable`. You may also add conformance to `JSONC extension User: JSONEncodable { func toJSON() throws -> AnyObject { - var result = [String: AnyObject]() - try result.encode(id, key: "id") - try result.encode(name, key: "full_name") - try result.encode(email, key: "email") - try result.encode(company, key: "company") - try result.encode(friends, key: "friends") - return result + return try JSONEncoder.create({ (encoder) -> Void in + try encoder.encode(id, key: "id") + try encoder.encode(name, key: "full_name") + try encoder.encode(email, key: "email") + try encoder.encode(company, key: "company") + try encoder.encode(friends, key: "friends") + }) } } extension Company: JSONEncodable {} /*: -The default implementation of `func JSONEncode()` inspects the properties of your type using reflection. (Like in `Company`.) If you need a different mapping, you can provide your own implementation (like in `User`.) +The default implementation of `func toJSON()` inspects the properties of your type using reflection. (Like in `Company`.) If you need a different mapping, you can provide your own implementation (like in `User`.) */ /*: @@ -54,13 +54,14 @@ We'll add conformance to `JSONDecodable`. You may also add conformance to `JSONC */ extension User: JSONDecodable { - init?(JSONDictionary: [String:AnyObject]) { + init?(JSONDictionary: JSONObject) { + let decoder = JSONDecoder(object: JSONDictionary) do { - id = try JSONDictionary.decode("id") - name = try JSONDictionary.decode("full_name") - email = try JSONDictionary.decode("email") - company = try JSONDictionary.decode("company") - friends = try JSONDictionary.decode("friends") + id = try decoder.decode("id") + name = try decoder.decode("full_name") + email = try decoder.decode("email") + company = try decoder.decode("company") + friends = try decoder.decode("friends") } catch { return nil @@ -69,10 +70,11 @@ extension User: JSONDecodable { } extension Company: JSONDecodable { - init?(JSONDictionary: [String:AnyObject]) { + init?(JSONDictionary: JSONObject) { + let decoder = JSONDecoder(object: JSONDictionary) do { - name = try JSONDictionary.decode("name") - address = try JSONDictionary.decode("address") + name = try decoder.decode("name") + address = try decoder.decode("address") } catch { return nil @@ -81,7 +83,7 @@ extension Company: JSONDecodable { } /*: -Simply provide the implementations for `init?(JSONDictionary: [String:AnyObject])`. As before, you can use this to configure the mapping between keys in the `Dictionary` to properties in your structs and classes. +Simply provide the implementations for `init?(JSONDictionary: JSONObject)`. As before, you can use this to configure the mapping between keys in the `Dictionary` to properties in your structs and classes. */ /*: @@ -109,7 +111,7 @@ print("Initial JSON:\n\(JSON)\n\n") /*: We can instantiate `User` using one of provided initializers: -- `init(JSONDictionary: [String: AnyObject])` +- `init(JSONDictionary: JSONObject)` - `init?(JSONString: String)` */ @@ -125,7 +127,7 @@ And encode it to JSON using one of the provided methods: do { let dict = try user.toJSON() - print("Encoded: \n\(dict as! [String: AnyObject])\n\n") + print("Encoded: \n\(dict as! JSONObject)\n\n") } catch { print("Error: \(error)") diff --git a/README.md b/README.md index 7cb7838..5d1924c 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,14 @@ github "matthewcheok/JSONCodable" and then run `carthage update` -**Swift 2.0 Required** -This project uses a variety of Swift features including *Protocol Extensions* and *Error Handling* available in Swift 2.0 +**TLDR** +- Uses Protocol Extensions +- Error Handling +- Supports `let` properties +- Supports `enum` properties backed by compatible values -**Breaking Change** -`JSONCodable` now supports `let` properties. You now implement `init?(JSONDictionary: [String:AnyObject])` instead of `func JSONDecode()` and `func toJSON()` instead of `func JSONEncode()`. +**Change Log** +- Moved encoding and decoding methods to a helper class --- @@ -64,13 +67,13 @@ Simply add conformance to `JSONEncodable` (or to `JSONCodable`): ```swift extension User: JSONEncodable { func toJSON() throws -> AnyObject { - var result: [String: AnyObject] = [:] - try result.encode(id, key: "id") - try result.encode(name, key: "full_name") - try result.encode(email, key: "email") - try result.encode(company, key: "company") - try result.encode(friends, key: "friends") - return result + return try JSONEncoder.create({ (encoder) -> Void in + try encoder.encode(id, key: "id") + try encoder.encode(name, key: "full_name") + try encoder.encode(email, key: "email") + try encoder.encode(company, key: "company") + try encoder.encode(friends, key: "friends") + }) } } @@ -111,36 +114,36 @@ Result: Simply add conformance to `JSONDecodable` (or to `JSONCodable`): ```swift extension User: JSONDecodable { - init?(JSONDictionary: [String:AnyObject]) { + init?(JSONDictionary: JSONObject) { + let decoder = JSONDecoder(object: JSONDictionary) do { - id = try JSONDictionary.decode("id") - name = try JSONDictionary.decode("full_name") - email = try JSONDictionary.decode("email") - company = try JSONDictionary.decode("company") - friends = try JSONDictionary.decode("friends") + id = try decoder.decode("id") + name = try decoder.decode("full_name") + email = try decoder.decode("email") + company = try decoder.decode("company") + friends = try decoder.decode("friends") } catch { - print(error) return nil } } } extension Company: JSONDecodable { - init?(JSONDictionary: [String:AnyObject]) { + init?(JSONDictionary: JSONObject) { + let decoder = JSONDecoder(object: JSONDictionary) do { - name = try JSONDictionary.decode("name") - address = try JSONDictionary.decode("address") + name = try decoder.decode("name") + address = try decoder.decode("address") } catch { - print(error) return nil } } } ``` -Simply provide the implementations for `init?(JSONDictionary: [String:AnyObject])`. +Simply provide the implementations for `init?(JSONDictionary: [JSONObject])` where `JSONObject` is a typealias for `[String:AnyObject]`. As before, you can use this to configure the mapping between keys in the Dictionary to properties in your structs and classes. ```swift @@ -225,8 +228,7 @@ Feel free to suggest more! ## Example code -Refer to the `Demo` project in the workspace for more information. -You might experience issues executing the playground in Xcode 7.0 Beta. +Refer to the included playground in the workspace for more details. ## License From d32396079b3ab8b75add45bc66ee58ff508d9f90 Mon Sep 17 00:00:00 2001 From: Matthew Cheok Date: Sun, 18 Oct 2015 08:54:24 -0700 Subject: [PATCH 4/4] Updated podspec --- JSONCodable.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONCodable.podspec b/JSONCodable.podspec index bedf3c0..923bec5 100644 --- a/JSONCodable.podspec +++ b/JSONCodable.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'JSONCodable' - s.version = '1.1.0' + s.version = '2.0' s.ios.deployment_target = '8.0' s.osx.deployment_target = '10.10' s.license = { :type => 'MIT', :file => 'LICENSE' }