├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── ELCodable.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcshareddata │ └── xcschemes │ │ └── ELCodable.xcscheme └── xcuserdata │ └── brandon.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── ELCodable ├── Decimal.swift ├── Decodable.swift ├── DecodableExtensions.swift ├── DecodeOperators.swift ├── ELCodable.h ├── Encodable.swift ├── EncodableExtensions.swift ├── EncodeOperators.swift ├── Info.plist └── JSON.swift ├── ELCodableTests ├── DecimalTests.swift ├── DynamicKeyTest.swift ├── DynamicKeyedData.json ├── ELCodableTests.swift ├── Info.plist ├── JSONTests.swift ├── KeyPathTests.swift ├── NestedErrorTesting.json ├── NestedErrorTesting.swift ├── OptionalTests.json ├── OptionalTests.swift └── jsontest_models.json ├── ELCodable_osx ├── ELCodable_osx.h └── Info.plist ├── ELCodable_osxTests ├── ELCodable_osxTests.swift └── Info.plist ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcscmblueprint 19 | *.xcsettings 20 | *.xcuserstate 21 | .DS_Store 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode10.2 3 | script: 4 | - xcodebuild -scheme ELCodable -sdk iphonesimulator clean test -destination 'OS=12.2,name=iPhone Xʀ' CODE_SIGNING_REQUIRED=NO 5 | - xcodebuild -scheme ELCodable_static -sdk iphonesimulator clean build -destination 'OS=12.2,name=iPhone Xʀ' CODE_SIGNING_REQUIRED=NO 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # [5.0.0](https://github.com/Electrode-iOS/ELCodable/releases/tag/v5.0.0) 2 | 3 | - Update to Xcode 10.2 and Swift 5 4 | 5 | # [4.1.0](https://github.com/Electrode-iOS/ELCodable/releases/tag/v4.1.0) 6 | 7 | - Add a target that builds a static framework for iOS platform. 8 | 9 | # [4.0.1](https://github.com/Electrode-iOS/ELCodable/releases/tag/v4.0.1) 10 | 11 | - Xcode 9.3 updates 12 | 13 | # [4.0.0](https://github.com/Electrode-iOS/ELCodable/releases/tag/v4.0.0) 14 | 15 | - Migrate to Swift 4 16 | 17 | # [3.2.0](https://github.com/Electrode-iOS/ELCodable/releases/tag/v3.2.0) 18 | 19 | - Use default settings for bitcode 20 | - Added support for building with Xcode 9, backward compatible with Xcode 8 21 | 22 | 23 | # [3.1.0](https://github.com/Electrode-iOS/ELCodable/releases/tag/v3.1.0) 24 | 25 | - Added support for encoding `NSNull` as JSON null. 26 | 27 | # [3.0.1](https://github.com/Electrode-iOS/ELCodable/releases/tag/v3.0.1) 28 | 29 | - Resolved Xcode 8.3 warnings 30 | 31 | # [3.0.0](https://github.com/Electrode-iOS/ELCodable/releases/tag/v3.0.0) 32 | 33 | - Update to support Swift 3 34 | 35 | # [2.1.1](https://github.com/Electrode-iOS/ELCodable/releases/tag/v2.1.1) 36 | 37 | - Update OS X target to use Swift 2.3 38 | 39 | # [2.1.0](https://github.com/Electrode-iOS/ELCodable/releases/tag/v2.1.0) 40 | 41 | - Added support for Xcode 8, Swift 2.3, and iOS SDK 10 42 | 43 | # [2.0.0](https://github.com/Electrode-iOS/ELCodable/releases/tag/v2.0.0) 44 | 45 | ## New Features 46 | 47 | - Added subscript to retrieve values for a given key index or array indexes. 48 | - Added an OS X target. 49 | - Made `data()` public. 50 | 51 | ## Removals 52 | 53 | - Remove return values from compound operators 54 | - Remove extra `inout` from `*` operator 55 | -------------------------------------------------------------------------------- /ELCodable.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3EA176DD20E44AE600D50AF4 /* DecodeOperators.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F351BF4AD6C006459C7 /* DecodeOperators.swift */; }; 11 | 3EA176DE20E44AE600D50AF4 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F3F1BF4AD80006459C7 /* JSON.swift */; }; 12 | 3EA176DF20E44AE600D50AF4 /* Decodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F331BF4AD6C006459C7 /* Decodable.swift */; }; 13 | 3EA176E020E44AE600D50AF4 /* DecodableExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F341BF4AD6C006459C7 /* DecodableExtensions.swift */; }; 14 | 3EA176E120E44AE600D50AF4 /* Encodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F391BF4AD79006459C7 /* Encodable.swift */; }; 15 | 3EA176E220E44AE600D50AF4 /* EncodableExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F3A1BF4AD79006459C7 /* EncodableExtensions.swift */; }; 16 | 3EA176E320E44AE600D50AF4 /* EncodeOperators.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F3B1BF4AD79006459C7 /* EncodeOperators.swift */; }; 17 | 3EA176E420E44AE600D50AF4 /* Decimal.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F411BF4AD92006459C7 /* Decimal.swift */; }; 18 | 3EA176E720E44AE600D50AF4 /* ELCodable.h in Headers */ = {isa = PBXBuildFile; fileRef = CA0C9F191BF4AD08006459C7 /* ELCodable.h */; settings = {ATTRIBUTES = (Public, ); }; }; 19 | CA0C9F1A1BF4AD08006459C7 /* ELCodable.h in Headers */ = {isa = PBXBuildFile; fileRef = CA0C9F191BF4AD08006459C7 /* ELCodable.h */; settings = {ATTRIBUTES = (Public, ); }; }; 20 | CA0C9F211BF4AD08006459C7 /* ELCodable.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CA0C9F161BF4AD08006459C7 /* ELCodable.framework */; }; 21 | CA0C9F261BF4AD08006459C7 /* ELCodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F251BF4AD08006459C7 /* ELCodableTests.swift */; }; 22 | CA0C9F361BF4AD6C006459C7 /* Decodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F331BF4AD6C006459C7 /* Decodable.swift */; }; 23 | CA0C9F371BF4AD6C006459C7 /* DecodableExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F341BF4AD6C006459C7 /* DecodableExtensions.swift */; }; 24 | CA0C9F381BF4AD6C006459C7 /* DecodeOperators.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F351BF4AD6C006459C7 /* DecodeOperators.swift */; }; 25 | CA0C9F3C1BF4AD79006459C7 /* Encodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F391BF4AD79006459C7 /* Encodable.swift */; }; 26 | CA0C9F3D1BF4AD79006459C7 /* EncodableExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F3A1BF4AD79006459C7 /* EncodableExtensions.swift */; }; 27 | CA0C9F3E1BF4AD79006459C7 /* EncodeOperators.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F3B1BF4AD79006459C7 /* EncodeOperators.swift */; }; 28 | CA0C9F401BF4AD80006459C7 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F3F1BF4AD80006459C7 /* JSON.swift */; }; 29 | CA0C9F421BF4AD92006459C7 /* Decimal.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F411BF4AD92006459C7 /* Decimal.swift */; }; 30 | CA0C9F451BF4ADD3006459C7 /* jsontest_models.json in Resources */ = {isa = PBXBuildFile; fileRef = CA0C9F441BF4ADD3006459C7 /* jsontest_models.json */; }; 31 | CA0C9F471BF4ADE0006459C7 /* JSONTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F461BF4ADE0006459C7 /* JSONTests.swift */; }; 32 | CA3952A71C45C44200A24CDF /* NestedErrorTesting.json in Resources */ = {isa = PBXBuildFile; fileRef = CA3952A61C45C44200A24CDF /* NestedErrorTesting.json */; }; 33 | CA3952A91C45C44B00A24CDF /* NestedErrorTesting.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA3952A81C45C44B00A24CDF /* NestedErrorTesting.swift */; }; 34 | CAD3E3E31D416DCE00AEDD28 /* DynamicKeyedData.json in Resources */ = {isa = PBXBuildFile; fileRef = CAD3E3E11D416DCE00AEDD28 /* DynamicKeyedData.json */; }; 35 | CAD3E3E41D416DCE00AEDD28 /* OptionalTests.json in Resources */ = {isa = PBXBuildFile; fileRef = CAD3E3E21D416DCE00AEDD28 /* OptionalTests.json */; }; 36 | CAD3E3E61D416DD700AEDD28 /* OptionalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD3E3E51D416DD700AEDD28 /* OptionalTests.swift */; }; 37 | CAD3E3E81D416DDF00AEDD28 /* DynamicKeyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD3E3E71D416DDF00AEDD28 /* DynamicKeyTest.swift */; }; 38 | CAD3E3EA1D416DF000AEDD28 /* KeyPathTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD3E3E91D416DF000AEDD28 /* KeyPathTests.swift */; }; 39 | CAE55C011D13A61900411727 /* ELCodable_osx.h in Headers */ = {isa = PBXBuildFile; fileRef = CAE55C001D13A61900411727 /* ELCodable_osx.h */; settings = {ATTRIBUTES = (Public, ); }; }; 40 | CAE55C081D13A61A00411727 /* ELCodable.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CAE55BFE1D13A61900411727 /* ELCodable.framework */; }; 41 | CAE55C0D1D13A61A00411727 /* ELCodable_osxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAE55C0C1D13A61A00411727 /* ELCodable_osxTests.swift */; }; 42 | CAE55C171D13A63D00411727 /* Decodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F331BF4AD6C006459C7 /* Decodable.swift */; }; 43 | CAE55C181D13A63D00411727 /* DecodableExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F341BF4AD6C006459C7 /* DecodableExtensions.swift */; }; 44 | CAE55C191D13A63D00411727 /* DecodeOperators.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F351BF4AD6C006459C7 /* DecodeOperators.swift */; }; 45 | CAE55C1A1D13A64100411727 /* Encodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F391BF4AD79006459C7 /* Encodable.swift */; }; 46 | CAE55C1B1D13A64100411727 /* EncodableExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F3A1BF4AD79006459C7 /* EncodableExtensions.swift */; }; 47 | CAE55C1C1D13A64100411727 /* EncodeOperators.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F3B1BF4AD79006459C7 /* EncodeOperators.swift */; }; 48 | CAE55C1D1D13A64400411727 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F3F1BF4AD80006459C7 /* JSON.swift */; }; 49 | CAE55C1E1D13A64700411727 /* Decimal.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C9F411BF4AD92006459C7 /* Decimal.swift */; }; 50 | CAF4B88F1C496F36000A42C7 /* DecimalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAF4B88E1C496F36000A42C7 /* DecimalTests.swift */; }; 51 | /* End PBXBuildFile section */ 52 | 53 | /* Begin PBXContainerItemProxy section */ 54 | CA0C9F221BF4AD08006459C7 /* PBXContainerItemProxy */ = { 55 | isa = PBXContainerItemProxy; 56 | containerPortal = CA0C9F0D1BF4AD08006459C7 /* Project object */; 57 | proxyType = 1; 58 | remoteGlobalIDString = CA0C9F151BF4AD08006459C7; 59 | remoteInfo = ELCodable; 60 | }; 61 | CAE55C091D13A61A00411727 /* PBXContainerItemProxy */ = { 62 | isa = PBXContainerItemProxy; 63 | containerPortal = CA0C9F0D1BF4AD08006459C7 /* Project object */; 64 | proxyType = 1; 65 | remoteGlobalIDString = CAE55BFD1D13A61900411727; 66 | remoteInfo = ELCodable_osx; 67 | }; 68 | /* End PBXContainerItemProxy section */ 69 | 70 | /* Begin PBXFileReference section */ 71 | 3EA176ED20E44AE600D50AF4 /* ELCodable.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ELCodable.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 72 | CA0C9F161BF4AD08006459C7 /* ELCodable.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ELCodable.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 73 | CA0C9F191BF4AD08006459C7 /* ELCodable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ELCodable.h; sourceTree = ""; }; 74 | CA0C9F1B1BF4AD08006459C7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 75 | CA0C9F201BF4AD08006459C7 /* ELCodableTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ELCodableTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 76 | CA0C9F251BF4AD08006459C7 /* ELCodableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ELCodableTests.swift; sourceTree = ""; }; 77 | CA0C9F271BF4AD08006459C7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 78 | CA0C9F331BF4AD6C006459C7 /* Decodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Decodable.swift; sourceTree = ""; }; 79 | CA0C9F341BF4AD6C006459C7 /* DecodableExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DecodableExtensions.swift; sourceTree = ""; }; 80 | CA0C9F351BF4AD6C006459C7 /* DecodeOperators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DecodeOperators.swift; sourceTree = ""; }; 81 | CA0C9F391BF4AD79006459C7 /* Encodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Encodable.swift; sourceTree = ""; }; 82 | CA0C9F3A1BF4AD79006459C7 /* EncodableExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EncodableExtensions.swift; sourceTree = ""; }; 83 | CA0C9F3B1BF4AD79006459C7 /* EncodeOperators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EncodeOperators.swift; sourceTree = ""; }; 84 | CA0C9F3F1BF4AD80006459C7 /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; 85 | CA0C9F411BF4AD92006459C7 /* Decimal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Decimal.swift; sourceTree = ""; }; 86 | CA0C9F441BF4ADD3006459C7 /* jsontest_models.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = jsontest_models.json; sourceTree = ""; }; 87 | CA0C9F461BF4ADE0006459C7 /* JSONTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONTests.swift; sourceTree = ""; }; 88 | CA3952A61C45C44200A24CDF /* NestedErrorTesting.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = NestedErrorTesting.json; sourceTree = ""; }; 89 | CA3952A81C45C44B00A24CDF /* NestedErrorTesting.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NestedErrorTesting.swift; sourceTree = ""; }; 90 | CAD3E3E11D416DCE00AEDD28 /* DynamicKeyedData.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = DynamicKeyedData.json; sourceTree = ""; }; 91 | CAD3E3E21D416DCE00AEDD28 /* OptionalTests.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = OptionalTests.json; sourceTree = ""; }; 92 | CAD3E3E51D416DD700AEDD28 /* OptionalTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptionalTests.swift; sourceTree = ""; }; 93 | CAD3E3E71D416DDF00AEDD28 /* DynamicKeyTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicKeyTest.swift; sourceTree = ""; }; 94 | CAD3E3E91D416DF000AEDD28 /* KeyPathTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyPathTests.swift; sourceTree = ""; }; 95 | CAE55BFE1D13A61900411727 /* ELCodable.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ELCodable.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 96 | CAE55C001D13A61900411727 /* ELCodable_osx.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ELCodable_osx.h; sourceTree = ""; }; 97 | CAE55C021D13A61900411727 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 98 | CAE55C071D13A61A00411727 /* ELCodable_osxTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ELCodable_osxTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 99 | CAE55C0C1D13A61A00411727 /* ELCodable_osxTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ELCodable_osxTests.swift; sourceTree = ""; }; 100 | CAE55C0E1D13A61A00411727 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 101 | CAF4B88E1C496F36000A42C7 /* DecimalTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DecimalTests.swift; sourceTree = ""; }; 102 | /* End PBXFileReference section */ 103 | 104 | /* Begin PBXFrameworksBuildPhase section */ 105 | 3EA176E520E44AE600D50AF4 /* Frameworks */ = { 106 | isa = PBXFrameworksBuildPhase; 107 | buildActionMask = 2147483647; 108 | files = ( 109 | ); 110 | runOnlyForDeploymentPostprocessing = 0; 111 | }; 112 | CA0C9F121BF4AD08006459C7 /* Frameworks */ = { 113 | isa = PBXFrameworksBuildPhase; 114 | buildActionMask = 2147483647; 115 | files = ( 116 | ); 117 | runOnlyForDeploymentPostprocessing = 0; 118 | }; 119 | CA0C9F1D1BF4AD08006459C7 /* Frameworks */ = { 120 | isa = PBXFrameworksBuildPhase; 121 | buildActionMask = 2147483647; 122 | files = ( 123 | CA0C9F211BF4AD08006459C7 /* ELCodable.framework in Frameworks */, 124 | ); 125 | runOnlyForDeploymentPostprocessing = 0; 126 | }; 127 | CAE55BFA1D13A61900411727 /* Frameworks */ = { 128 | isa = PBXFrameworksBuildPhase; 129 | buildActionMask = 2147483647; 130 | files = ( 131 | ); 132 | runOnlyForDeploymentPostprocessing = 0; 133 | }; 134 | CAE55C041D13A61A00411727 /* Frameworks */ = { 135 | isa = PBXFrameworksBuildPhase; 136 | buildActionMask = 2147483647; 137 | files = ( 138 | CAE55C081D13A61A00411727 /* ELCodable.framework in Frameworks */, 139 | ); 140 | runOnlyForDeploymentPostprocessing = 0; 141 | }; 142 | /* End PBXFrameworksBuildPhase section */ 143 | 144 | /* Begin PBXGroup section */ 145 | CA0C9F0C1BF4AD08006459C7 = { 146 | isa = PBXGroup; 147 | children = ( 148 | CA0C9F181BF4AD08006459C7 /* ELCodable */, 149 | CA0C9F241BF4AD08006459C7 /* ELCodableTests */, 150 | CAE55BFF1D13A61900411727 /* ELCodable_osx */, 151 | CAE55C0B1D13A61A00411727 /* ELCodable_osxTests */, 152 | CA0C9F171BF4AD08006459C7 /* Products */, 153 | ); 154 | sourceTree = ""; 155 | }; 156 | CA0C9F171BF4AD08006459C7 /* Products */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | CA0C9F161BF4AD08006459C7 /* ELCodable.framework */, 160 | CA0C9F201BF4AD08006459C7 /* ELCodableTests.xctest */, 161 | CAE55BFE1D13A61900411727 /* ELCodable.framework */, 162 | CAE55C071D13A61A00411727 /* ELCodable_osxTests.xctest */, 163 | 3EA176ED20E44AE600D50AF4 /* ELCodable.framework */, 164 | ); 165 | name = Products; 166 | sourceTree = ""; 167 | }; 168 | CA0C9F181BF4AD08006459C7 /* ELCodable */ = { 169 | isa = PBXGroup; 170 | children = ( 171 | CA0C9F301BF4AD39006459C7 /* Decodable */, 172 | CA0C9F311BF4AD41006459C7 /* Encodable */, 173 | CA0C9F321BF4AD47006459C7 /* JSON */, 174 | CA0C9F191BF4AD08006459C7 /* ELCodable.h */, 175 | CA0C9F411BF4AD92006459C7 /* Decimal.swift */, 176 | CA0C9F1B1BF4AD08006459C7 /* Info.plist */, 177 | ); 178 | path = ELCodable; 179 | sourceTree = ""; 180 | }; 181 | CA0C9F241BF4AD08006459C7 /* ELCodableTests */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | CA0C9F431BF4ADC4006459C7 /* Test Data */, 185 | CA0C9F251BF4AD08006459C7 /* ELCodableTests.swift */, 186 | CA3952A81C45C44B00A24CDF /* NestedErrorTesting.swift */, 187 | CA0C9F461BF4ADE0006459C7 /* JSONTests.swift */, 188 | CAF4B88E1C496F36000A42C7 /* DecimalTests.swift */, 189 | CAD3E3E51D416DD700AEDD28 /* OptionalTests.swift */, 190 | CAD3E3E71D416DDF00AEDD28 /* DynamicKeyTest.swift */, 191 | CAD3E3E91D416DF000AEDD28 /* KeyPathTests.swift */, 192 | CA0C9F271BF4AD08006459C7 /* Info.plist */, 193 | ); 194 | path = ELCodableTests; 195 | sourceTree = ""; 196 | }; 197 | CA0C9F301BF4AD39006459C7 /* Decodable */ = { 198 | isa = PBXGroup; 199 | children = ( 200 | CA0C9F331BF4AD6C006459C7 /* Decodable.swift */, 201 | CA0C9F341BF4AD6C006459C7 /* DecodableExtensions.swift */, 202 | CA0C9F351BF4AD6C006459C7 /* DecodeOperators.swift */, 203 | ); 204 | name = Decodable; 205 | sourceTree = ""; 206 | }; 207 | CA0C9F311BF4AD41006459C7 /* Encodable */ = { 208 | isa = PBXGroup; 209 | children = ( 210 | CA0C9F391BF4AD79006459C7 /* Encodable.swift */, 211 | CA0C9F3A1BF4AD79006459C7 /* EncodableExtensions.swift */, 212 | CA0C9F3B1BF4AD79006459C7 /* EncodeOperators.swift */, 213 | ); 214 | name = Encodable; 215 | sourceTree = ""; 216 | }; 217 | CA0C9F321BF4AD47006459C7 /* JSON */ = { 218 | isa = PBXGroup; 219 | children = ( 220 | CA0C9F3F1BF4AD80006459C7 /* JSON.swift */, 221 | ); 222 | name = JSON; 223 | sourceTree = ""; 224 | }; 225 | CA0C9F431BF4ADC4006459C7 /* Test Data */ = { 226 | isa = PBXGroup; 227 | children = ( 228 | CA3952A61C45C44200A24CDF /* NestedErrorTesting.json */, 229 | CA0C9F441BF4ADD3006459C7 /* jsontest_models.json */, 230 | CAD3E3E11D416DCE00AEDD28 /* DynamicKeyedData.json */, 231 | CAD3E3E21D416DCE00AEDD28 /* OptionalTests.json */, 232 | ); 233 | name = "Test Data"; 234 | sourceTree = ""; 235 | }; 236 | CAE55BFF1D13A61900411727 /* ELCodable_osx */ = { 237 | isa = PBXGroup; 238 | children = ( 239 | CAE55C001D13A61900411727 /* ELCodable_osx.h */, 240 | CAE55C021D13A61900411727 /* Info.plist */, 241 | ); 242 | path = ELCodable_osx; 243 | sourceTree = ""; 244 | }; 245 | CAE55C0B1D13A61A00411727 /* ELCodable_osxTests */ = { 246 | isa = PBXGroup; 247 | children = ( 248 | CAE55C0C1D13A61A00411727 /* ELCodable_osxTests.swift */, 249 | CAE55C0E1D13A61A00411727 /* Info.plist */, 250 | ); 251 | path = ELCodable_osxTests; 252 | sourceTree = ""; 253 | }; 254 | /* End PBXGroup section */ 255 | 256 | /* Begin PBXHeadersBuildPhase section */ 257 | 3EA176E620E44AE600D50AF4 /* Headers */ = { 258 | isa = PBXHeadersBuildPhase; 259 | buildActionMask = 2147483647; 260 | files = ( 261 | 3EA176E720E44AE600D50AF4 /* ELCodable.h in Headers */, 262 | ); 263 | runOnlyForDeploymentPostprocessing = 0; 264 | }; 265 | CA0C9F131BF4AD08006459C7 /* Headers */ = { 266 | isa = PBXHeadersBuildPhase; 267 | buildActionMask = 2147483647; 268 | files = ( 269 | CA0C9F1A1BF4AD08006459C7 /* ELCodable.h in Headers */, 270 | ); 271 | runOnlyForDeploymentPostprocessing = 0; 272 | }; 273 | CAE55BFB1D13A61900411727 /* Headers */ = { 274 | isa = PBXHeadersBuildPhase; 275 | buildActionMask = 2147483647; 276 | files = ( 277 | CAE55C011D13A61900411727 /* ELCodable_osx.h in Headers */, 278 | ); 279 | runOnlyForDeploymentPostprocessing = 0; 280 | }; 281 | /* End PBXHeadersBuildPhase section */ 282 | 283 | /* Begin PBXNativeTarget section */ 284 | 3EA176DB20E44AE600D50AF4 /* ELCodable_static */ = { 285 | isa = PBXNativeTarget; 286 | buildConfigurationList = 3EA176E920E44AE600D50AF4 /* Build configuration list for PBXNativeTarget "ELCodable_static" */; 287 | buildPhases = ( 288 | 3EA176DC20E44AE600D50AF4 /* Sources */, 289 | 3EA176E520E44AE600D50AF4 /* Frameworks */, 290 | 3EA176E620E44AE600D50AF4 /* Headers */, 291 | 3EA176E820E44AE600D50AF4 /* Resources */, 292 | ); 293 | buildRules = ( 294 | ); 295 | dependencies = ( 296 | ); 297 | name = ELCodable_static; 298 | productName = ELCodable; 299 | productReference = 3EA176ED20E44AE600D50AF4 /* ELCodable.framework */; 300 | productType = "com.apple.product-type.framework"; 301 | }; 302 | CA0C9F151BF4AD08006459C7 /* ELCodable */ = { 303 | isa = PBXNativeTarget; 304 | buildConfigurationList = CA0C9F2A1BF4AD08006459C7 /* Build configuration list for PBXNativeTarget "ELCodable" */; 305 | buildPhases = ( 306 | CA0C9F111BF4AD08006459C7 /* Sources */, 307 | CA0C9F121BF4AD08006459C7 /* Frameworks */, 308 | CA0C9F131BF4AD08006459C7 /* Headers */, 309 | CA0C9F141BF4AD08006459C7 /* Resources */, 310 | ); 311 | buildRules = ( 312 | ); 313 | dependencies = ( 314 | ); 315 | name = ELCodable; 316 | productName = ELCodable; 317 | productReference = CA0C9F161BF4AD08006459C7 /* ELCodable.framework */; 318 | productType = "com.apple.product-type.framework"; 319 | }; 320 | CA0C9F1F1BF4AD08006459C7 /* ELCodableTests */ = { 321 | isa = PBXNativeTarget; 322 | buildConfigurationList = CA0C9F2D1BF4AD08006459C7 /* Build configuration list for PBXNativeTarget "ELCodableTests" */; 323 | buildPhases = ( 324 | CA0C9F1C1BF4AD08006459C7 /* Sources */, 325 | CA0C9F1D1BF4AD08006459C7 /* Frameworks */, 326 | CA0C9F1E1BF4AD08006459C7 /* Resources */, 327 | ); 328 | buildRules = ( 329 | ); 330 | dependencies = ( 331 | CA0C9F231BF4AD08006459C7 /* PBXTargetDependency */, 332 | ); 333 | name = ELCodableTests; 334 | productName = ELCodableTests; 335 | productReference = CA0C9F201BF4AD08006459C7 /* ELCodableTests.xctest */; 336 | productType = "com.apple.product-type.bundle.unit-test"; 337 | }; 338 | CAE55BFD1D13A61900411727 /* ELCodable_osx */ = { 339 | isa = PBXNativeTarget; 340 | buildConfigurationList = CAE55C0F1D13A61A00411727 /* Build configuration list for PBXNativeTarget "ELCodable_osx" */; 341 | buildPhases = ( 342 | CAE55BF91D13A61900411727 /* Sources */, 343 | CAE55BFA1D13A61900411727 /* Frameworks */, 344 | CAE55BFB1D13A61900411727 /* Headers */, 345 | CAE55BFC1D13A61900411727 /* Resources */, 346 | ); 347 | buildRules = ( 348 | ); 349 | dependencies = ( 350 | ); 351 | name = ELCodable_osx; 352 | productName = ELCodable_osx; 353 | productReference = CAE55BFE1D13A61900411727 /* ELCodable.framework */; 354 | productType = "com.apple.product-type.framework"; 355 | }; 356 | CAE55C061D13A61A00411727 /* ELCodable_osxTests */ = { 357 | isa = PBXNativeTarget; 358 | buildConfigurationList = CAE55C131D13A61A00411727 /* Build configuration list for PBXNativeTarget "ELCodable_osxTests" */; 359 | buildPhases = ( 360 | CAE55C031D13A61A00411727 /* Sources */, 361 | CAE55C041D13A61A00411727 /* Frameworks */, 362 | CAE55C051D13A61A00411727 /* Resources */, 363 | ); 364 | buildRules = ( 365 | ); 366 | dependencies = ( 367 | CAE55C0A1D13A61A00411727 /* PBXTargetDependency */, 368 | ); 369 | name = ELCodable_osxTests; 370 | productName = ELCodable_osxTests; 371 | productReference = CAE55C071D13A61A00411727 /* ELCodable_osxTests.xctest */; 372 | productType = "com.apple.product-type.bundle.unit-test"; 373 | }; 374 | /* End PBXNativeTarget section */ 375 | 376 | /* Begin PBXProject section */ 377 | CA0C9F0D1BF4AD08006459C7 /* Project object */ = { 378 | isa = PBXProject; 379 | attributes = { 380 | LastSwiftUpdateCheck = 0730; 381 | LastUpgradeCheck = 1020; 382 | ORGANIZATIONNAME = WalmartLabs; 383 | TargetAttributes = { 384 | CA0C9F151BF4AD08006459C7 = { 385 | CreatedOnToolsVersion = 7.1; 386 | LastSwiftMigration = 1020; 387 | }; 388 | CA0C9F1F1BF4AD08006459C7 = { 389 | CreatedOnToolsVersion = 7.1; 390 | LastSwiftMigration = 1020; 391 | }; 392 | CAE55BFD1D13A61900411727 = { 393 | CreatedOnToolsVersion = 7.3.1; 394 | LastSwiftMigration = 0830; 395 | }; 396 | CAE55C061D13A61A00411727 = { 397 | CreatedOnToolsVersion = 7.3.1; 398 | LastSwiftMigration = 0830; 399 | }; 400 | }; 401 | }; 402 | buildConfigurationList = CA0C9F101BF4AD08006459C7 /* Build configuration list for PBXProject "ELCodable" */; 403 | compatibilityVersion = "Xcode 3.2"; 404 | developmentRegion = en; 405 | hasScannedForEncodings = 0; 406 | knownRegions = ( 407 | en, 408 | Base, 409 | ); 410 | mainGroup = CA0C9F0C1BF4AD08006459C7; 411 | productRefGroup = CA0C9F171BF4AD08006459C7 /* Products */; 412 | projectDirPath = ""; 413 | projectRoot = ""; 414 | targets = ( 415 | CA0C9F151BF4AD08006459C7 /* ELCodable */, 416 | 3EA176DB20E44AE600D50AF4 /* ELCodable_static */, 417 | CA0C9F1F1BF4AD08006459C7 /* ELCodableTests */, 418 | CAE55BFD1D13A61900411727 /* ELCodable_osx */, 419 | CAE55C061D13A61A00411727 /* ELCodable_osxTests */, 420 | ); 421 | }; 422 | /* End PBXProject section */ 423 | 424 | /* Begin PBXResourcesBuildPhase section */ 425 | 3EA176E820E44AE600D50AF4 /* Resources */ = { 426 | isa = PBXResourcesBuildPhase; 427 | buildActionMask = 2147483647; 428 | files = ( 429 | ); 430 | runOnlyForDeploymentPostprocessing = 0; 431 | }; 432 | CA0C9F141BF4AD08006459C7 /* Resources */ = { 433 | isa = PBXResourcesBuildPhase; 434 | buildActionMask = 2147483647; 435 | files = ( 436 | ); 437 | runOnlyForDeploymentPostprocessing = 0; 438 | }; 439 | CA0C9F1E1BF4AD08006459C7 /* Resources */ = { 440 | isa = PBXResourcesBuildPhase; 441 | buildActionMask = 2147483647; 442 | files = ( 443 | CA3952A71C45C44200A24CDF /* NestedErrorTesting.json in Resources */, 444 | CAD3E3E31D416DCE00AEDD28 /* DynamicKeyedData.json in Resources */, 445 | CA0C9F451BF4ADD3006459C7 /* jsontest_models.json in Resources */, 446 | CAD3E3E41D416DCE00AEDD28 /* OptionalTests.json in Resources */, 447 | ); 448 | runOnlyForDeploymentPostprocessing = 0; 449 | }; 450 | CAE55BFC1D13A61900411727 /* Resources */ = { 451 | isa = PBXResourcesBuildPhase; 452 | buildActionMask = 2147483647; 453 | files = ( 454 | ); 455 | runOnlyForDeploymentPostprocessing = 0; 456 | }; 457 | CAE55C051D13A61A00411727 /* Resources */ = { 458 | isa = PBXResourcesBuildPhase; 459 | buildActionMask = 2147483647; 460 | files = ( 461 | ); 462 | runOnlyForDeploymentPostprocessing = 0; 463 | }; 464 | /* End PBXResourcesBuildPhase section */ 465 | 466 | /* Begin PBXSourcesBuildPhase section */ 467 | 3EA176DC20E44AE600D50AF4 /* Sources */ = { 468 | isa = PBXSourcesBuildPhase; 469 | buildActionMask = 2147483647; 470 | files = ( 471 | 3EA176DD20E44AE600D50AF4 /* DecodeOperators.swift in Sources */, 472 | 3EA176DE20E44AE600D50AF4 /* JSON.swift in Sources */, 473 | 3EA176DF20E44AE600D50AF4 /* Decodable.swift in Sources */, 474 | 3EA176E020E44AE600D50AF4 /* DecodableExtensions.swift in Sources */, 475 | 3EA176E120E44AE600D50AF4 /* Encodable.swift in Sources */, 476 | 3EA176E220E44AE600D50AF4 /* EncodableExtensions.swift in Sources */, 477 | 3EA176E320E44AE600D50AF4 /* EncodeOperators.swift in Sources */, 478 | 3EA176E420E44AE600D50AF4 /* Decimal.swift in Sources */, 479 | ); 480 | runOnlyForDeploymentPostprocessing = 0; 481 | }; 482 | CA0C9F111BF4AD08006459C7 /* Sources */ = { 483 | isa = PBXSourcesBuildPhase; 484 | buildActionMask = 2147483647; 485 | files = ( 486 | CA0C9F381BF4AD6C006459C7 /* DecodeOperators.swift in Sources */, 487 | CA0C9F401BF4AD80006459C7 /* JSON.swift in Sources */, 488 | CA0C9F361BF4AD6C006459C7 /* Decodable.swift in Sources */, 489 | CA0C9F371BF4AD6C006459C7 /* DecodableExtensions.swift in Sources */, 490 | CA0C9F3C1BF4AD79006459C7 /* Encodable.swift in Sources */, 491 | CA0C9F3D1BF4AD79006459C7 /* EncodableExtensions.swift in Sources */, 492 | CA0C9F3E1BF4AD79006459C7 /* EncodeOperators.swift in Sources */, 493 | CA0C9F421BF4AD92006459C7 /* Decimal.swift in Sources */, 494 | ); 495 | runOnlyForDeploymentPostprocessing = 0; 496 | }; 497 | CA0C9F1C1BF4AD08006459C7 /* Sources */ = { 498 | isa = PBXSourcesBuildPhase; 499 | buildActionMask = 2147483647; 500 | files = ( 501 | CAD3E3E61D416DD700AEDD28 /* OptionalTests.swift in Sources */, 502 | CA3952A91C45C44B00A24CDF /* NestedErrorTesting.swift in Sources */, 503 | CA0C9F261BF4AD08006459C7 /* ELCodableTests.swift in Sources */, 504 | CAD3E3E81D416DDF00AEDD28 /* DynamicKeyTest.swift in Sources */, 505 | CA0C9F471BF4ADE0006459C7 /* JSONTests.swift in Sources */, 506 | CAD3E3EA1D416DF000AEDD28 /* KeyPathTests.swift in Sources */, 507 | CAF4B88F1C496F36000A42C7 /* DecimalTests.swift in Sources */, 508 | ); 509 | runOnlyForDeploymentPostprocessing = 0; 510 | }; 511 | CAE55BF91D13A61900411727 /* Sources */ = { 512 | isa = PBXSourcesBuildPhase; 513 | buildActionMask = 2147483647; 514 | files = ( 515 | CAE55C191D13A63D00411727 /* DecodeOperators.swift in Sources */, 516 | CAE55C1D1D13A64400411727 /* JSON.swift in Sources */, 517 | CAE55C171D13A63D00411727 /* Decodable.swift in Sources */, 518 | CAE55C181D13A63D00411727 /* DecodableExtensions.swift in Sources */, 519 | CAE55C1A1D13A64100411727 /* Encodable.swift in Sources */, 520 | CAE55C1B1D13A64100411727 /* EncodableExtensions.swift in Sources */, 521 | CAE55C1C1D13A64100411727 /* EncodeOperators.swift in Sources */, 522 | CAE55C1E1D13A64700411727 /* Decimal.swift in Sources */, 523 | ); 524 | runOnlyForDeploymentPostprocessing = 0; 525 | }; 526 | CAE55C031D13A61A00411727 /* Sources */ = { 527 | isa = PBXSourcesBuildPhase; 528 | buildActionMask = 2147483647; 529 | files = ( 530 | CAE55C0D1D13A61A00411727 /* ELCodable_osxTests.swift in Sources */, 531 | ); 532 | runOnlyForDeploymentPostprocessing = 0; 533 | }; 534 | /* End PBXSourcesBuildPhase section */ 535 | 536 | /* Begin PBXTargetDependency section */ 537 | CA0C9F231BF4AD08006459C7 /* PBXTargetDependency */ = { 538 | isa = PBXTargetDependency; 539 | target = CA0C9F151BF4AD08006459C7 /* ELCodable */; 540 | targetProxy = CA0C9F221BF4AD08006459C7 /* PBXContainerItemProxy */; 541 | }; 542 | CAE55C0A1D13A61A00411727 /* PBXTargetDependency */ = { 543 | isa = PBXTargetDependency; 544 | target = CAE55BFD1D13A61900411727 /* ELCodable_osx */; 545 | targetProxy = CAE55C091D13A61A00411727 /* PBXContainerItemProxy */; 546 | }; 547 | /* End PBXTargetDependency section */ 548 | 549 | /* Begin XCBuildConfiguration section */ 550 | 3EA176EA20E44AE600D50AF4 /* Debug */ = { 551 | isa = XCBuildConfiguration; 552 | buildSettings = { 553 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 554 | DEFINES_MODULE = YES; 555 | DYLIB_COMPATIBILITY_VERSION = 1; 556 | DYLIB_CURRENT_VERSION = 1; 557 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 558 | INFOPLIST_FILE = ELCodable/Info.plist; 559 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 560 | MACH_O_TYPE = staticlib; 561 | PRODUCT_BUNDLE_IDENTIFIER = com.walmartlabs.ELCodable; 562 | PRODUCT_MODULE_NAME = "$(PRODUCT_NAME)"; 563 | PRODUCT_NAME = ELCodable; 564 | SKIP_INSTALL = YES; 565 | SWIFT_VERSION = 4.0; 566 | }; 567 | name = Debug; 568 | }; 569 | 3EA176EB20E44AE600D50AF4 /* QADeployment */ = { 570 | isa = XCBuildConfiguration; 571 | buildSettings = { 572 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 573 | DEFINES_MODULE = YES; 574 | DYLIB_COMPATIBILITY_VERSION = 1; 575 | DYLIB_CURRENT_VERSION = 1; 576 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 577 | INFOPLIST_FILE = ELCodable/Info.plist; 578 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 579 | MACH_O_TYPE = staticlib; 580 | PRODUCT_BUNDLE_IDENTIFIER = com.walmartlabs.ELCodable; 581 | PRODUCT_MODULE_NAME = "$(PRODUCT_NAME)"; 582 | PRODUCT_NAME = ELCodable; 583 | SKIP_INSTALL = YES; 584 | SWIFT_VERSION = 4.0; 585 | }; 586 | name = QADeployment; 587 | }; 588 | 3EA176EC20E44AE600D50AF4 /* Release */ = { 589 | isa = XCBuildConfiguration; 590 | buildSettings = { 591 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 592 | DEFINES_MODULE = YES; 593 | DYLIB_COMPATIBILITY_VERSION = 1; 594 | DYLIB_CURRENT_VERSION = 1; 595 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 596 | INFOPLIST_FILE = ELCodable/Info.plist; 597 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 598 | MACH_O_TYPE = staticlib; 599 | PRODUCT_BUNDLE_IDENTIFIER = com.walmartlabs.ELCodable; 600 | PRODUCT_MODULE_NAME = "$(PRODUCT_NAME)"; 601 | PRODUCT_NAME = ELCodable; 602 | SKIP_INSTALL = YES; 603 | SWIFT_VERSION = 4.0; 604 | }; 605 | name = Release; 606 | }; 607 | CA0C9F281BF4AD08006459C7 /* Debug */ = { 608 | isa = XCBuildConfiguration; 609 | buildSettings = { 610 | ALWAYS_SEARCH_USER_PATHS = NO; 611 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 612 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 613 | CLANG_CXX_LIBRARY = "libc++"; 614 | CLANG_ENABLE_MODULES = YES; 615 | CLANG_ENABLE_OBJC_ARC = YES; 616 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 617 | CLANG_WARN_BOOL_CONVERSION = YES; 618 | CLANG_WARN_COMMA = YES; 619 | CLANG_WARN_CONSTANT_CONVERSION = YES; 620 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 621 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 622 | CLANG_WARN_EMPTY_BODY = YES; 623 | CLANG_WARN_ENUM_CONVERSION = YES; 624 | CLANG_WARN_INFINITE_RECURSION = YES; 625 | CLANG_WARN_INT_CONVERSION = YES; 626 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 627 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 628 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 629 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 630 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 631 | CLANG_WARN_STRICT_PROTOTYPES = YES; 632 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 633 | CLANG_WARN_UNREACHABLE_CODE = YES; 634 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 635 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 636 | COPY_PHASE_STRIP = NO; 637 | CURRENT_PROJECT_VERSION = 1; 638 | DEBUG_INFORMATION_FORMAT = dwarf; 639 | ENABLE_STRICT_OBJC_MSGSEND = YES; 640 | ENABLE_TESTABILITY = YES; 641 | GCC_C_LANGUAGE_STANDARD = gnu99; 642 | GCC_DYNAMIC_NO_PIC = NO; 643 | GCC_NO_COMMON_BLOCKS = YES; 644 | GCC_OPTIMIZATION_LEVEL = 0; 645 | GCC_PREPROCESSOR_DEFINITIONS = ( 646 | "DEBUG=1", 647 | "$(inherited)", 648 | ); 649 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 650 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 651 | GCC_WARN_UNDECLARED_SELECTOR = YES; 652 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 653 | GCC_WARN_UNUSED_FUNCTION = YES; 654 | GCC_WARN_UNUSED_VARIABLE = YES; 655 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 656 | MTL_ENABLE_DEBUG_INFO = YES; 657 | ONLY_ACTIVE_ARCH = YES; 658 | SDKROOT = iphoneos; 659 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 660 | TARGETED_DEVICE_FAMILY = "1,2"; 661 | VERSIONING_SYSTEM = "apple-generic"; 662 | VERSION_INFO_PREFIX = ""; 663 | }; 664 | name = Debug; 665 | }; 666 | CA0C9F291BF4AD08006459C7 /* Release */ = { 667 | isa = XCBuildConfiguration; 668 | buildSettings = { 669 | ALWAYS_SEARCH_USER_PATHS = NO; 670 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 671 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 672 | CLANG_CXX_LIBRARY = "libc++"; 673 | CLANG_ENABLE_MODULES = YES; 674 | CLANG_ENABLE_OBJC_ARC = YES; 675 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 676 | CLANG_WARN_BOOL_CONVERSION = YES; 677 | CLANG_WARN_COMMA = YES; 678 | CLANG_WARN_CONSTANT_CONVERSION = YES; 679 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 680 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 681 | CLANG_WARN_EMPTY_BODY = YES; 682 | CLANG_WARN_ENUM_CONVERSION = YES; 683 | CLANG_WARN_INFINITE_RECURSION = YES; 684 | CLANG_WARN_INT_CONVERSION = YES; 685 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 686 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 687 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 688 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 689 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 690 | CLANG_WARN_STRICT_PROTOTYPES = YES; 691 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 692 | CLANG_WARN_UNREACHABLE_CODE = YES; 693 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 694 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 695 | COPY_PHASE_STRIP = NO; 696 | CURRENT_PROJECT_VERSION = 1; 697 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 698 | ENABLE_NS_ASSERTIONS = NO; 699 | ENABLE_STRICT_OBJC_MSGSEND = YES; 700 | GCC_C_LANGUAGE_STANDARD = gnu99; 701 | GCC_NO_COMMON_BLOCKS = YES; 702 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 703 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 704 | GCC_WARN_UNDECLARED_SELECTOR = YES; 705 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 706 | GCC_WARN_UNUSED_FUNCTION = YES; 707 | GCC_WARN_UNUSED_VARIABLE = YES; 708 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 709 | MTL_ENABLE_DEBUG_INFO = NO; 710 | SDKROOT = iphoneos; 711 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 712 | TARGETED_DEVICE_FAMILY = "1,2"; 713 | VALIDATE_PRODUCT = YES; 714 | VERSIONING_SYSTEM = "apple-generic"; 715 | VERSION_INFO_PREFIX = ""; 716 | }; 717 | name = Release; 718 | }; 719 | CA0C9F2B1BF4AD08006459C7 /* Debug */ = { 720 | isa = XCBuildConfiguration; 721 | buildSettings = { 722 | CLANG_ENABLE_MODULES = YES; 723 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 724 | DEFINES_MODULE = YES; 725 | DYLIB_COMPATIBILITY_VERSION = 1; 726 | DYLIB_CURRENT_VERSION = 1; 727 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 728 | INFOPLIST_FILE = ELCodable/Info.plist; 729 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 730 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 731 | PRODUCT_BUNDLE_IDENTIFIER = com.walmartlabs.ELCodable; 732 | PRODUCT_NAME = "$(TARGET_NAME)"; 733 | SKIP_INSTALL = YES; 734 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 735 | SWIFT_VERSION = 5.0; 736 | }; 737 | name = Debug; 738 | }; 739 | CA0C9F2C1BF4AD08006459C7 /* Release */ = { 740 | isa = XCBuildConfiguration; 741 | buildSettings = { 742 | CLANG_ENABLE_MODULES = YES; 743 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 744 | DEFINES_MODULE = YES; 745 | DYLIB_COMPATIBILITY_VERSION = 1; 746 | DYLIB_CURRENT_VERSION = 1; 747 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 748 | ENABLE_TESTABILITY = YES; 749 | INFOPLIST_FILE = ELCodable/Info.plist; 750 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 751 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 752 | PRODUCT_BUNDLE_IDENTIFIER = com.walmartlabs.ELCodable; 753 | PRODUCT_NAME = "$(TARGET_NAME)"; 754 | SKIP_INSTALL = YES; 755 | SWIFT_VERSION = 5.0; 756 | }; 757 | name = Release; 758 | }; 759 | CA0C9F2E1BF4AD08006459C7 /* Debug */ = { 760 | isa = XCBuildConfiguration; 761 | buildSettings = { 762 | DEVELOPMENT_TEAM = ""; 763 | INFOPLIST_FILE = ELCodableTests/Info.plist; 764 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 765 | PRODUCT_BUNDLE_IDENTIFIER = com.walmartlabs.ELCodableTests; 766 | PRODUCT_NAME = "$(TARGET_NAME)"; 767 | SWIFT_VERSION = 5.0; 768 | }; 769 | name = Debug; 770 | }; 771 | CA0C9F2F1BF4AD08006459C7 /* Release */ = { 772 | isa = XCBuildConfiguration; 773 | buildSettings = { 774 | DEVELOPMENT_TEAM = ""; 775 | INFOPLIST_FILE = ELCodableTests/Info.plist; 776 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 777 | PRODUCT_BUNDLE_IDENTIFIER = com.walmartlabs.ELCodableTests; 778 | PRODUCT_NAME = "$(TARGET_NAME)"; 779 | SWIFT_VERSION = 5.0; 780 | }; 781 | name = Release; 782 | }; 783 | CAE55C101D13A61A00411727 /* Debug */ = { 784 | isa = XCBuildConfiguration; 785 | buildSettings = { 786 | CLANG_ANALYZER_NONNULL = YES; 787 | CODE_SIGN_IDENTITY = "-"; 788 | COMBINE_HIDPI_IMAGES = YES; 789 | DEFINES_MODULE = YES; 790 | DYLIB_COMPATIBILITY_VERSION = 1; 791 | DYLIB_CURRENT_VERSION = 1; 792 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 793 | FRAMEWORK_VERSION = A; 794 | INFOPLIST_FILE = ELCodable_osx/Info.plist; 795 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 796 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 797 | MACOSX_DEPLOYMENT_TARGET = 10.11; 798 | PRODUCT_BUNDLE_IDENTIFIER = com.walmart.ELCodable; 799 | PRODUCT_NAME = ELCodable; 800 | SDKROOT = macosx; 801 | SKIP_INSTALL = YES; 802 | SWIFT_VERSION = 3.0; 803 | }; 804 | name = Debug; 805 | }; 806 | CAE55C111D13A61A00411727 /* QADeployment */ = { 807 | isa = XCBuildConfiguration; 808 | buildSettings = { 809 | CLANG_ANALYZER_NONNULL = YES; 810 | CODE_SIGN_IDENTITY = "-"; 811 | COMBINE_HIDPI_IMAGES = YES; 812 | DEFINES_MODULE = YES; 813 | DYLIB_COMPATIBILITY_VERSION = 1; 814 | DYLIB_CURRENT_VERSION = 1; 815 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 816 | FRAMEWORK_VERSION = A; 817 | INFOPLIST_FILE = ELCodable_osx/Info.plist; 818 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 819 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 820 | MACOSX_DEPLOYMENT_TARGET = 10.11; 821 | PRODUCT_BUNDLE_IDENTIFIER = com.walmart.ELCodable; 822 | PRODUCT_NAME = ELCodable; 823 | SDKROOT = macosx; 824 | SKIP_INSTALL = YES; 825 | SWIFT_VERSION = 3.0; 826 | }; 827 | name = QADeployment; 828 | }; 829 | CAE55C121D13A61A00411727 /* Release */ = { 830 | isa = XCBuildConfiguration; 831 | buildSettings = { 832 | CLANG_ANALYZER_NONNULL = YES; 833 | CODE_SIGN_IDENTITY = "-"; 834 | COMBINE_HIDPI_IMAGES = YES; 835 | DEFINES_MODULE = YES; 836 | DYLIB_COMPATIBILITY_VERSION = 1; 837 | DYLIB_CURRENT_VERSION = 1; 838 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 839 | FRAMEWORK_VERSION = A; 840 | INFOPLIST_FILE = ELCodable_osx/Info.plist; 841 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 842 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 843 | MACOSX_DEPLOYMENT_TARGET = 10.11; 844 | PRODUCT_BUNDLE_IDENTIFIER = com.walmart.ELCodable; 845 | PRODUCT_NAME = ELCodable; 846 | SDKROOT = macosx; 847 | SKIP_INSTALL = YES; 848 | SWIFT_VERSION = 3.0; 849 | }; 850 | name = Release; 851 | }; 852 | CAE55C141D13A61A00411727 /* Debug */ = { 853 | isa = XCBuildConfiguration; 854 | buildSettings = { 855 | CLANG_ANALYZER_NONNULL = YES; 856 | CODE_SIGN_IDENTITY = "-"; 857 | COMBINE_HIDPI_IMAGES = YES; 858 | INFOPLIST_FILE = ELCodable_osxTests/Info.plist; 859 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 860 | MACOSX_DEPLOYMENT_TARGET = 10.11; 861 | PRODUCT_BUNDLE_IDENTIFIER = "com.walmart.ELCodable-osxTests"; 862 | PRODUCT_NAME = "$(TARGET_NAME)"; 863 | SDKROOT = macosx; 864 | SWIFT_VERSION = 3.0; 865 | }; 866 | name = Debug; 867 | }; 868 | CAE55C151D13A61A00411727 /* QADeployment */ = { 869 | isa = XCBuildConfiguration; 870 | buildSettings = { 871 | CLANG_ANALYZER_NONNULL = YES; 872 | CODE_SIGN_IDENTITY = "-"; 873 | COMBINE_HIDPI_IMAGES = YES; 874 | INFOPLIST_FILE = ELCodable_osxTests/Info.plist; 875 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 876 | MACOSX_DEPLOYMENT_TARGET = 10.11; 877 | PRODUCT_BUNDLE_IDENTIFIER = "com.walmart.ELCodable-osxTests"; 878 | PRODUCT_NAME = "$(TARGET_NAME)"; 879 | SDKROOT = macosx; 880 | SWIFT_VERSION = 3.0; 881 | }; 882 | name = QADeployment; 883 | }; 884 | CAE55C161D13A61A00411727 /* Release */ = { 885 | isa = XCBuildConfiguration; 886 | buildSettings = { 887 | CLANG_ANALYZER_NONNULL = YES; 888 | CODE_SIGN_IDENTITY = "-"; 889 | COMBINE_HIDPI_IMAGES = YES; 890 | INFOPLIST_FILE = ELCodable_osxTests/Info.plist; 891 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 892 | MACOSX_DEPLOYMENT_TARGET = 10.11; 893 | PRODUCT_BUNDLE_IDENTIFIER = "com.walmart.ELCodable-osxTests"; 894 | PRODUCT_NAME = "$(TARGET_NAME)"; 895 | SDKROOT = macosx; 896 | SWIFT_VERSION = 3.0; 897 | }; 898 | name = Release; 899 | }; 900 | DB5F6F481C77CC940048EA81 /* QADeployment */ = { 901 | isa = XCBuildConfiguration; 902 | buildSettings = { 903 | ALWAYS_SEARCH_USER_PATHS = NO; 904 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 905 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 906 | CLANG_CXX_LIBRARY = "libc++"; 907 | CLANG_ENABLE_MODULES = YES; 908 | CLANG_ENABLE_OBJC_ARC = YES; 909 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 910 | CLANG_WARN_BOOL_CONVERSION = YES; 911 | CLANG_WARN_COMMA = YES; 912 | CLANG_WARN_CONSTANT_CONVERSION = YES; 913 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 914 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 915 | CLANG_WARN_EMPTY_BODY = YES; 916 | CLANG_WARN_ENUM_CONVERSION = YES; 917 | CLANG_WARN_INFINITE_RECURSION = YES; 918 | CLANG_WARN_INT_CONVERSION = YES; 919 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 920 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 921 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 922 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 923 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 924 | CLANG_WARN_STRICT_PROTOTYPES = YES; 925 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 926 | CLANG_WARN_UNREACHABLE_CODE = YES; 927 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 928 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 929 | COPY_PHASE_STRIP = NO; 930 | CURRENT_PROJECT_VERSION = 1; 931 | DEBUG_INFORMATION_FORMAT = dwarf; 932 | ENABLE_STRICT_OBJC_MSGSEND = YES; 933 | ENABLE_TESTABILITY = YES; 934 | GCC_C_LANGUAGE_STANDARD = gnu99; 935 | GCC_DYNAMIC_NO_PIC = NO; 936 | GCC_NO_COMMON_BLOCKS = YES; 937 | GCC_OPTIMIZATION_LEVEL = 0; 938 | GCC_PREPROCESSOR_DEFINITIONS = ( 939 | "DEBUG=1", 940 | "$(inherited)", 941 | ); 942 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 943 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 944 | GCC_WARN_UNDECLARED_SELECTOR = YES; 945 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 946 | GCC_WARN_UNUSED_FUNCTION = YES; 947 | GCC_WARN_UNUSED_VARIABLE = YES; 948 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 949 | MTL_ENABLE_DEBUG_INFO = YES; 950 | ONLY_ACTIVE_ARCH = NO; 951 | SDKROOT = iphoneos; 952 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 953 | TARGETED_DEVICE_FAMILY = "1,2"; 954 | VERSIONING_SYSTEM = "apple-generic"; 955 | VERSION_INFO_PREFIX = ""; 956 | }; 957 | name = QADeployment; 958 | }; 959 | DB5F6F491C77CC940048EA81 /* QADeployment */ = { 960 | isa = XCBuildConfiguration; 961 | buildSettings = { 962 | CLANG_ENABLE_MODULES = YES; 963 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 964 | DEFINES_MODULE = YES; 965 | DYLIB_COMPATIBILITY_VERSION = 1; 966 | DYLIB_CURRENT_VERSION = 1; 967 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 968 | INFOPLIST_FILE = ELCodable/Info.plist; 969 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 970 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 971 | ONLY_ACTIVE_ARCH = NO; 972 | PRODUCT_BUNDLE_IDENTIFIER = com.walmartlabs.ELCodable; 973 | PRODUCT_NAME = "$(TARGET_NAME)"; 974 | SKIP_INSTALL = YES; 975 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 976 | SWIFT_VERSION = 5.0; 977 | }; 978 | name = QADeployment; 979 | }; 980 | DB5F6F4A1C77CC940048EA81 /* QADeployment */ = { 981 | isa = XCBuildConfiguration; 982 | buildSettings = { 983 | DEVELOPMENT_TEAM = ""; 984 | INFOPLIST_FILE = ELCodableTests/Info.plist; 985 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 986 | PRODUCT_BUNDLE_IDENTIFIER = com.walmartlabs.ELCodableTests; 987 | PRODUCT_NAME = "$(TARGET_NAME)"; 988 | SWIFT_VERSION = 5.0; 989 | }; 990 | name = QADeployment; 991 | }; 992 | /* End XCBuildConfiguration section */ 993 | 994 | /* Begin XCConfigurationList section */ 995 | 3EA176E920E44AE600D50AF4 /* Build configuration list for PBXNativeTarget "ELCodable_static" */ = { 996 | isa = XCConfigurationList; 997 | buildConfigurations = ( 998 | 3EA176EA20E44AE600D50AF4 /* Debug */, 999 | 3EA176EB20E44AE600D50AF4 /* QADeployment */, 1000 | 3EA176EC20E44AE600D50AF4 /* Release */, 1001 | ); 1002 | defaultConfigurationIsVisible = 0; 1003 | defaultConfigurationName = Release; 1004 | }; 1005 | CA0C9F101BF4AD08006459C7 /* Build configuration list for PBXProject "ELCodable" */ = { 1006 | isa = XCConfigurationList; 1007 | buildConfigurations = ( 1008 | CA0C9F281BF4AD08006459C7 /* Debug */, 1009 | DB5F6F481C77CC940048EA81 /* QADeployment */, 1010 | CA0C9F291BF4AD08006459C7 /* Release */, 1011 | ); 1012 | defaultConfigurationIsVisible = 0; 1013 | defaultConfigurationName = Release; 1014 | }; 1015 | CA0C9F2A1BF4AD08006459C7 /* Build configuration list for PBXNativeTarget "ELCodable" */ = { 1016 | isa = XCConfigurationList; 1017 | buildConfigurations = ( 1018 | CA0C9F2B1BF4AD08006459C7 /* Debug */, 1019 | DB5F6F491C77CC940048EA81 /* QADeployment */, 1020 | CA0C9F2C1BF4AD08006459C7 /* Release */, 1021 | ); 1022 | defaultConfigurationIsVisible = 0; 1023 | defaultConfigurationName = Release; 1024 | }; 1025 | CA0C9F2D1BF4AD08006459C7 /* Build configuration list for PBXNativeTarget "ELCodableTests" */ = { 1026 | isa = XCConfigurationList; 1027 | buildConfigurations = ( 1028 | CA0C9F2E1BF4AD08006459C7 /* Debug */, 1029 | DB5F6F4A1C77CC940048EA81 /* QADeployment */, 1030 | CA0C9F2F1BF4AD08006459C7 /* Release */, 1031 | ); 1032 | defaultConfigurationIsVisible = 0; 1033 | defaultConfigurationName = Release; 1034 | }; 1035 | CAE55C0F1D13A61A00411727 /* Build configuration list for PBXNativeTarget "ELCodable_osx" */ = { 1036 | isa = XCConfigurationList; 1037 | buildConfigurations = ( 1038 | CAE55C101D13A61A00411727 /* Debug */, 1039 | CAE55C111D13A61A00411727 /* QADeployment */, 1040 | CAE55C121D13A61A00411727 /* Release */, 1041 | ); 1042 | defaultConfigurationIsVisible = 0; 1043 | defaultConfigurationName = Release; 1044 | }; 1045 | CAE55C131D13A61A00411727 /* Build configuration list for PBXNativeTarget "ELCodable_osxTests" */ = { 1046 | isa = XCConfigurationList; 1047 | buildConfigurations = ( 1048 | CAE55C141D13A61A00411727 /* Debug */, 1049 | CAE55C151D13A61A00411727 /* QADeployment */, 1050 | CAE55C161D13A61A00411727 /* Release */, 1051 | ); 1052 | defaultConfigurationIsVisible = 0; 1053 | defaultConfigurationName = Release; 1054 | }; 1055 | /* End XCConfigurationList section */ 1056 | }; 1057 | rootObject = CA0C9F0D1BF4AD08006459C7 /* Project object */; 1058 | } 1059 | -------------------------------------------------------------------------------- /ELCodable.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ELCodable.xcodeproj/xcshareddata/xcschemes/ELCodable.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /ELCodable.xcodeproj/xcuserdata/brandon.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ELCodable.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | ELCodable.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 6 16 | 17 | ELCodable_osx.xcscheme 18 | 19 | orderHint 20 | 7 21 | 22 | ELCodable_osxTests.xcscheme 23 | 24 | orderHint 25 | 9 26 | 27 | 28 | SuppressBuildableAutocreation 29 | 30 | CA0C9F151BF4AD08006459C7 31 | 32 | primary 33 | 34 | 35 | CA0C9F1F1BF4AD08006459C7 36 | 37 | primary 38 | 39 | 40 | CAE55BBA1D13A2FD00411727 41 | 42 | primary 43 | 44 | 45 | CAE55BCE1D13A4E000411727 46 | 47 | primary 48 | 49 | 50 | CAE55BE91D13A53D00411727 51 | 52 | primary 53 | 54 | 55 | CAE55BFD1D13A61900411727 56 | 57 | primary 58 | 59 | 60 | CAE55C061D13A61A00411727 61 | 62 | primary 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /ELCodable/Decimal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Decimal.swift 3 | // Decimal 4 | // 5 | // Created by Brandon Sneed on 11/7/15. 6 | // Copyright © 2015 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct Decimal { 12 | public let value: NSDecimalNumber 13 | 14 | /// Create an instance initialized to zero. 15 | public init() { 16 | value = NSDecimalNumber.zero 17 | } 18 | /// Create an instance initialized to `value`. 19 | public init(_ value: NSDecimalNumber) { 20 | self.value = value 21 | } 22 | 23 | public init(_ value: NSNumber) { 24 | self.value = NSDecimalNumber(decimal: value.decimalValue) 25 | } 26 | 27 | public init(_ value: Float) { 28 | self.value = NSDecimalNumber(value: value) 29 | } 30 | 31 | public init(_ value: Double) { 32 | self.value = NSDecimalNumber(value: value) 33 | } 34 | 35 | public init(_ value: String) { 36 | self.value = NSDecimalNumber(string: value) 37 | } 38 | 39 | public init(_ v: UInt8) { 40 | value = NSDecimalNumber(value: v) 41 | } 42 | public init(_ v: Int8) { 43 | value = NSDecimalNumber(value: v) 44 | } 45 | public init(_ v: UInt16) { 46 | value = NSDecimalNumber(value: v) 47 | } 48 | public init(_ v: Int16) { 49 | value = NSDecimalNumber(value: v) 50 | } 51 | public init(_ v: UInt32) { 52 | value = NSDecimalNumber(value: v) 53 | } 54 | public init(_ v: Int32) { 55 | value = NSDecimalNumber(value: v) 56 | } 57 | public init(_ v: UInt64) { 58 | value = NSDecimalNumber(value: v) 59 | } 60 | public init(_ v: Int64) { 61 | value = NSDecimalNumber(value: v) 62 | } 63 | public init(_ v: UInt) { 64 | value = NSDecimalNumber(value: v) 65 | } 66 | public init(_ v: Int) { 67 | value = NSDecimalNumber(value: v) 68 | } 69 | } 70 | 71 | extension Decimal: Hashable { 72 | public func hash(into hasher: inout Hasher) { 73 | hasher.combine(value.hash) 74 | } 75 | } 76 | 77 | extension Decimal: CustomStringConvertible { 78 | /// A textual representation of `self`. 79 | public var description: String { 80 | return String(reflecting: value) 81 | } 82 | } 83 | 84 | extension Decimal: CustomDebugStringConvertible { 85 | /// A textual representation of `self`. 86 | public var debugDescription: String { 87 | return String(reflecting: value) 88 | } 89 | } 90 | 91 | extension Decimal /*: FloatingPointType*/ { // It complains about _BitsType missing, no idea wtf that is. 92 | /// The positive infinity. 93 | public static var infinity: Decimal { 94 | return Decimal(Double.infinity) 95 | } 96 | /// A quiet NaN. 97 | public static var NaN: Decimal { 98 | return Decimal(NSDecimalNumber.notANumber) 99 | } 100 | /// A quiet NaN. 101 | public static var quietNaN: Decimal { 102 | return NaN 103 | } 104 | /// `true` iff `self` is negative. 105 | public var isSignMinus: Bool { 106 | guard let doubleValue = doubleValue else { 107 | return false 108 | } 109 | 110 | return (doubleValue.sign == .minus) 111 | } 112 | /// `true` iff `self` is normal (not zero, subnormal, infinity, or 113 | /// NaN). 114 | public var isNormal: Bool { 115 | return doubleValue?.isNormal ?? false 116 | } 117 | /// `true` iff `self` is zero, subnormal, or normal (not infinity 118 | /// or NaN). 119 | public var isFinite: Bool { 120 | return doubleValue?.isFinite ?? false 121 | } 122 | /// `true` iff `self` is +0.0 or -0.0. 123 | public var isZero: Bool { 124 | return doubleValue?.isZero ?? false 125 | } 126 | /// `true` iff `self` is subnormal. 127 | public var isSubnormal: Bool { 128 | return doubleValue?.isSubnormal ?? false 129 | } 130 | /// `true` iff `self` is infinity. 131 | public var isInfinite: Bool { 132 | return doubleValue?.isInfinite ?? false 133 | } 134 | /// `true` iff `self` is NaN. 135 | public var isNaN: Bool { 136 | return doubleValue?.isNaN ?? false 137 | } 138 | /// `true` iff `self` is a signaling NaN. 139 | public var isSignaling: Bool { 140 | return doubleValue?.isSignalingNaN ?? false 141 | } 142 | 143 | private var doubleValue: Double? { 144 | return value as? Double 145 | } 146 | } 147 | 148 | extension Decimal: Equatable { 149 | public static func ==(lhs: Decimal, rhs: Decimal) -> Bool { 150 | return lhs.value.compare(rhs.value) == .orderedSame 151 | } 152 | } 153 | 154 | extension Decimal: Comparable { 155 | public static func <(lhs: Decimal, rhs: Decimal) -> Bool { 156 | return lhs.value.compare(rhs.value) == .orderedAscending 157 | } 158 | 159 | public static func <=(lhs: Decimal, rhs: Decimal) -> Bool { 160 | let result = lhs.value.compare(rhs.value) 161 | if result == .orderedAscending { 162 | return true 163 | } else if result == .orderedSame { 164 | return true 165 | } 166 | return false 167 | } 168 | 169 | public static func >=(lhs: Decimal, rhs: Decimal) -> Bool { 170 | let result = lhs.value.compare(rhs.value) 171 | if result == .orderedDescending { 172 | return true 173 | } else if result == .orderedSame { 174 | return true 175 | } 176 | return false 177 | } 178 | 179 | public static func >(lhs: Decimal, rhs: Decimal) -> Bool { 180 | return lhs.value.compare(rhs.value) == .orderedDescending 181 | } 182 | } 183 | 184 | extension Decimal: ExpressibleByIntegerLiteral { 185 | public init(integerLiteral value: IntegerLiteralType) { 186 | self.value = NSDecimalNumber(value: value as Int) 187 | } 188 | } 189 | 190 | // MARK: Addition operators 191 | 192 | public func +(lhs: Decimal, rhs: Decimal) -> Decimal { 193 | return Decimal(lhs.value.adding(rhs.value)) 194 | } 195 | 196 | public prefix func ++(lhs: Decimal) -> Decimal { 197 | return Decimal(lhs.value.adding(NSDecimalNumber.one)) 198 | } 199 | 200 | public postfix func ++(lhs: inout Decimal) -> Decimal { 201 | lhs = Decimal(lhs.value.adding(NSDecimalNumber.one)) 202 | return lhs 203 | } 204 | 205 | public func +=(lhs: inout Decimal, rhs: Decimal) { 206 | lhs = Decimal(lhs.value.adding(rhs.value)) 207 | } 208 | 209 | public func +=(lhs: inout Decimal, rhs: Int) { 210 | lhs = Decimal(lhs.value.adding(NSDecimalNumber(value: rhs as Int))) 211 | } 212 | 213 | public func +=(lhs: inout Decimal, rhs: Double) { 214 | lhs = Decimal(lhs.value.adding(NSDecimalNumber(value: rhs as Double))) 215 | } 216 | 217 | // MARK: Subtraction operators 218 | 219 | public prefix func -(x: Decimal) -> Decimal { 220 | return Decimal(x.value.multiplying(by: NSDecimalNumber(value: -1 as Int))) 221 | } 222 | 223 | public func -(lhs: Decimal, rhs: Decimal) -> Decimal { 224 | return Decimal(lhs.value.subtracting(rhs.value)) 225 | } 226 | 227 | public prefix func --(lhs: Decimal) -> Decimal { 228 | return Decimal(lhs.value.subtracting(NSDecimalNumber.one)) 229 | } 230 | 231 | public postfix func --(lhs: inout Decimal) -> Decimal { 232 | lhs = Decimal(lhs.value.subtracting(NSDecimalNumber.one)) 233 | return lhs 234 | } 235 | 236 | public func -=(lhs: inout Decimal, rhs: Decimal) { 237 | lhs = Decimal(lhs.value.subtracting(rhs.value)) 238 | } 239 | 240 | public func -=(lhs: inout Decimal, rhs: Int) { 241 | lhs = Decimal(lhs.value.subtracting(NSDecimalNumber(value: rhs as Int))) 242 | } 243 | 244 | public func -=(lhs: inout Decimal, rhs: Double) { 245 | lhs = Decimal(lhs.value.subtracting(NSDecimalNumber(value: rhs as Double))) 246 | } 247 | 248 | 249 | // MARK: Multiplication operators 250 | 251 | public func *(lhs: Decimal, rhs: Decimal) -> Decimal { 252 | return Decimal(lhs.value.multiplying(by: rhs.value)) 253 | } 254 | 255 | public func *=(lhs: inout Decimal, rhs: Decimal) { 256 | lhs = Decimal(lhs.value.multiplying(by: rhs.value)) 257 | } 258 | 259 | public func *=(lhs: inout Decimal, rhs: Int) { 260 | lhs = Decimal(lhs.value.multiplying(by: NSDecimalNumber(value: rhs as Int))) 261 | } 262 | 263 | public func *=(lhs: inout Decimal, rhs: Double) { 264 | lhs = Decimal(lhs.value.multiplying(by: NSDecimalNumber(value: rhs as Double))) 265 | } 266 | 267 | // MARK: Division operators 268 | 269 | public func /(lhs: Decimal, rhs: Decimal) -> Decimal { 270 | return Decimal(lhs.value.dividing(by: rhs.value)) 271 | } 272 | 273 | public func /=(lhs: inout Decimal, rhs: Decimal) { 274 | lhs = Decimal(lhs.value.dividing(by: rhs.value)) 275 | } 276 | 277 | public func /=(lhs: inout Decimal, rhs: Int) { 278 | lhs = Decimal(lhs.value.dividing(by: NSDecimalNumber(value: rhs as Int))) 279 | } 280 | 281 | public func /=(lhs: inout Decimal, rhs: Double) { 282 | lhs = Decimal(lhs.value.dividing(by: NSDecimalNumber(value: rhs as Double))) 283 | } 284 | 285 | // MARK: Power-of operators 286 | 287 | public func ^(lhs: Decimal, rhs: Int) -> Decimal { 288 | return Decimal(lhs.value.raising(toPower: rhs)) 289 | } 290 | 291 | -------------------------------------------------------------------------------- /ELCodable/Decodable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Decodable.swift 3 | // Codable 4 | // 5 | // Created by Brandon Sneed on 11/2/15. 6 | // Copyright © 2015 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum DecodeError: Error { 12 | case emptyJSON 13 | case undecodable 14 | case validationUnimplemented 15 | case validationFailed 16 | case notFound(key: String) 17 | } 18 | 19 | public protocol Decodable { 20 | static func decode(_ json: JSON?) throws -> Self 21 | func validate() throws -> Self 22 | } 23 | 24 | public extension Decodable { 25 | func validate() throws -> Self { 26 | // do nothing. user to override. 27 | throw DecodeError.validationUnimplemented 28 | //return self 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ELCodable/DecodableExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DecodableExtensions.swift 3 | // Codable 4 | // 5 | // Created by Brandon Sneed on 11/4/15. 6 | // Copyright © 2015 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension String: Decodable { 12 | public static func decode(_ json: JSON?) throws -> String { 13 | if let value = json?.string { 14 | return value 15 | } 16 | if json != nil { 17 | throw DecodeError.undecodable 18 | } else { 19 | throw DecodeError.emptyJSON 20 | } 21 | } 22 | } 23 | 24 | extension Float: Decodable { 25 | public static func decode(_ json: JSON?) throws -> Float { 26 | if let value = json?.float { 27 | return value 28 | } 29 | throw DecodeError.undecodable 30 | } 31 | } 32 | 33 | extension Double: Decodable { 34 | public static func decode(_ json: JSON?) throws -> Double { 35 | if let value = json?.double { 36 | return value 37 | } 38 | throw DecodeError.undecodable 39 | } 40 | } 41 | 42 | extension Int: Decodable { 43 | public static func decode(_ json: JSON?) throws -> Int { 44 | if let value = json?.int { 45 | return value 46 | } 47 | throw DecodeError.undecodable 48 | } 49 | } 50 | 51 | extension Int64: Decodable { 52 | public static func decode(_ json: JSON?) throws -> Int64 { 53 | if let value = json?.int64 { 54 | return value 55 | } 56 | throw DecodeError.undecodable 57 | } 58 | } 59 | 60 | extension UInt: Decodable { 61 | public static func decode(_ json: JSON?) throws -> UInt { 62 | if let value = json?.uInt { 63 | return value 64 | } 65 | throw DecodeError.undecodable 66 | } 67 | } 68 | 69 | extension UInt64: Decodable { 70 | public static func decode(_ json: JSON?) throws -> UInt64 { 71 | if let value = json?.uInt64 { 72 | return value 73 | } 74 | throw DecodeError.undecodable 75 | } 76 | } 77 | 78 | extension Bool: Decodable { 79 | public static func decode(_ json: JSON?) throws -> Bool { 80 | if let value = json?.bool { 81 | return value 82 | } 83 | throw DecodeError.undecodable 84 | } 85 | } 86 | 87 | extension Decimal: Decodable { 88 | public static func decode(_ json: JSON?) throws -> Decimal { 89 | if let value = json?.decimal { 90 | return Decimal(value) 91 | } 92 | throw DecodeError.undecodable 93 | } 94 | } 95 | 96 | extension Array where Element: Decodable { 97 | public static func decode(_ json: JSON?) throws -> [Element] { 98 | guard let items = json?.array else { 99 | throw DecodeError.undecodable 100 | } 101 | 102 | var decodedItems = [Element]() 103 | 104 | for item in items { 105 | let decodedItem = try Element.decode(item) 106 | decodedItems.append(decodedItem) 107 | } 108 | 109 | return decodedItems 110 | } 111 | } 112 | 113 | extension Dictionary where Key: ExpressibleByStringLiteral, Value: Decodable { 114 | public static func decode(_ json: JSON?) throws -> [String: JSON] { 115 | guard let value = json?.dictionary else { 116 | throw DecodeError.undecodable 117 | } 118 | 119 | return value 120 | } 121 | } 122 | 123 | 124 | -------------------------------------------------------------------------------- /ELCodable/DecodeOperators.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DecodeOperators.swift 3 | // Codable 4 | // 5 | // Created by Brandon Sneed on 11/3/15. 6 | // Copyright © 2015 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | //infix operator ==> { associativity right precedence 150 } 12 | 13 | infix operator ==> : Decode 14 | precedencegroup Decode { associativity: right } 15 | 16 | public func ==> (lhs: JSON?, rhs: String) throws -> T { 17 | guard let json = lhs else { 18 | throw DecodeError.emptyJSON 19 | } 20 | 21 | do { 22 | let value: T? = try? T.decode(json[rhs]) 23 | if let value = value { 24 | return value 25 | } else { 26 | throw DecodeError.notFound(key: rhs) 27 | } 28 | } catch let error { 29 | throw error 30 | } 31 | } 32 | 33 | public func ==> (lhs: JSON?, rhs: String) throws -> [T] { 34 | guard let json = lhs else { 35 | throw DecodeError.emptyJSON 36 | } 37 | 38 | guard let array = json[rhs]?.array else { 39 | throw DecodeError.notFound(key: rhs) 40 | } 41 | 42 | var results = [T]() 43 | 44 | for json in array { 45 | // will throw a NotFound() if this decode fails. 46 | let value = try T.decode(json) 47 | results.append(value) 48 | } 49 | 50 | return results 51 | } 52 | 53 | public func ==> (lhs: JSON?, rhs: String) throws -> T? { 54 | guard let json = lhs else { 55 | throw DecodeError.emptyJSON 56 | } 57 | 58 | let value = try? T.decode(json[rhs]) 59 | if let value = value { 60 | return value 61 | } else { 62 | return nil 63 | } 64 | } 65 | 66 | public func ==> (lhs: JSON?, rhs: String) throws -> [T]? { 67 | guard let json = lhs else { 68 | throw DecodeError.emptyJSON 69 | } 70 | 71 | guard let array = json[rhs]?.array else { 72 | return nil 73 | } 74 | 75 | var results = [T]() 76 | 77 | for json in array { 78 | if let value = try? T.decode(json) { 79 | results.append(value) 80 | } 81 | } 82 | 83 | return results 84 | } 85 | 86 | -------------------------------------------------------------------------------- /ELCodable/ELCodable.h: -------------------------------------------------------------------------------- 1 | // 2 | // ELCodable.h 3 | // ELCodable 4 | // 5 | // Created by Brandon Sneed on 11/12/15. 6 | // Copyright © 2015 WalmartLabs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for ELCodable. 12 | FOUNDATION_EXPORT double ELCodableVersionNumber; 13 | 14 | //! Project version string for ELCodable. 15 | FOUNDATION_EXPORT const unsigned char ELCodableVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /ELCodable/Encodable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Encodable.swift 3 | // Codable 4 | // 5 | // Created by Brandon Sneed on 11/9/15. 6 | // Copyright © 2015 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum EncodeError: Error { 12 | case unencodable 13 | case validationUnumplemented 14 | case validationFailed 15 | } 16 | 17 | public protocol Encodable { 18 | func encode() throws -> JSON 19 | } 20 | 21 | public typealias EncodeFormat = Array<(String, JSON)> 22 | 23 | public extension Encodable { 24 | func validateEncode() throws -> Self { 25 | // do nothing. user to override. 26 | throw EncodeError.validationUnumplemented 27 | } 28 | 29 | func encodeToJSON(_ format: EncodeFormat) throws -> JSON { 30 | var json = JSON() 31 | for tuple in format { 32 | json[tuple.0] = tuple.1 33 | } 34 | return json 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ELCodable/EncodableExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EncodableExtensions.swift 3 | // Codable 4 | // 5 | // Created by Brandon Sneed on 11/10/15. 6 | // Copyright © 2015 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension String: Encodable { 12 | public func encode() throws -> JSON { 13 | return JSON(self) 14 | } 15 | } 16 | 17 | extension Float: Encodable { 18 | public func encode() throws -> JSON { 19 | return JSON(self) 20 | } 21 | } 22 | 23 | extension Double: Encodable { 24 | public func encode() throws -> JSON { 25 | return JSON(self) 26 | } 27 | } 28 | 29 | extension Int: Encodable { 30 | public func encode() throws -> JSON { 31 | return JSON(self) 32 | } 33 | } 34 | 35 | extension Int64: Encodable { 36 | public func encode() throws -> JSON { 37 | return JSON(NSNumber(value: self as Int64)) 38 | } 39 | } 40 | 41 | extension UInt: Encodable { 42 | public func encode() throws -> JSON { 43 | return JSON(self) 44 | } 45 | } 46 | 47 | extension UInt64: Encodable { 48 | public func encode() throws -> JSON { 49 | return JSON(NSNumber(value: self as UInt64)) 50 | } 51 | } 52 | 53 | extension Bool: Encodable { 54 | public func encode() throws -> JSON { 55 | return JSON(self) 56 | } 57 | } 58 | 59 | extension Decimal: Encodable { 60 | public func encode() throws -> JSON { 61 | return JSON(self.value) 62 | } 63 | } 64 | 65 | extension Array where Element: Encodable { 66 | public func encode() throws -> JSON { 67 | var array = [Any]() 68 | for item in self { 69 | let jsonItem = try item.encode() 70 | if let object = jsonItem.object { 71 | array.append(object) 72 | } 73 | } 74 | return JSON(array) 75 | } 76 | } 77 | 78 | extension NSNull: Encodable { 79 | public func encode() throws -> JSON { 80 | return JSON(self) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /ELCodable/EncodeOperators.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EncodeOperators.swift 3 | // Codable 4 | // 5 | // Created by Brandon Sneed on 11/10/15. 6 | // Copyright © 2015 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | infix operator <== : Encode 12 | precedencegroup Encode { associativity: right } 13 | 14 | public func <== (lhs: String, rhs: T) throws -> (String, JSON) { 15 | let value = try? rhs.encode() 16 | if let value = value { 17 | return (lhs, value) 18 | } else { 19 | throw EncodeError.unencodable 20 | } 21 | } 22 | 23 | public func <== (lhs: String, rhs: [T]) throws -> (String, JSON) { 24 | let value = try? rhs.encode() 25 | if let value = value { 26 | return (lhs, value) 27 | } else { 28 | throw EncodeError.unencodable 29 | } 30 | } 31 | 32 | public func <== (lhs: String, rhs: T?) throws -> (String, JSON) { 33 | if rhs == nil { 34 | return (lhs, JSON()) 35 | } 36 | 37 | let value = ((try? rhs?.encode()) as JSON??) 38 | if let value = value { 39 | return (lhs, value!) 40 | } else { 41 | return (lhs, JSON()) 42 | } 43 | } 44 | 45 | public func <== (lhs: String, rhs: [T]?) throws -> (String, JSON) { 46 | if rhs == nil { 47 | return (lhs, JSON()) 48 | } 49 | 50 | let value = ((try? rhs?.encode()) as JSON??) 51 | if let value = value { 52 | return (lhs, value!) 53 | } else { 54 | return (lhs, JSON()) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ELCodable/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 5.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ELCodable/JSON.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JSON2.swift 3 | // THGModel 4 | // 5 | // Created by Brandon Sneed on 9/12/15. 6 | // Copyright © 2015 theholygrail. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum JSONError: Error { 12 | case invalidJSON 13 | } 14 | 15 | public enum JSONType: Int { 16 | case number 17 | case string 18 | case bool 19 | case array 20 | case dictionary 21 | case null 22 | case unknown 23 | } 24 | 25 | 26 | public struct JSON: Equatable { 27 | 28 | public var object: Any? 29 | 30 | public init() { 31 | self.object = nil 32 | } 33 | 34 | public init(_ object: Any?) { 35 | self.object = object 36 | } 37 | 38 | public init(json: JSON) { 39 | self.object = json.object 40 | } 41 | 42 | public init?(data: Data?) { 43 | if let data = data { 44 | do { 45 | let object: Any = try JSONSerialization.jsonObject(with: data, options: .allowFragments) 46 | self.object = object 47 | } catch let error as NSError { 48 | debugPrint(error) 49 | } 50 | } 51 | else { 52 | return nil 53 | } 54 | } 55 | 56 | public init?(path: String) { 57 | let exists = FileManager.default.fileExists(atPath: path) 58 | if exists { 59 | let data = try? Data(contentsOf: Foundation.URL(fileURLWithPath: path)) 60 | self.init(data: data) 61 | } else { 62 | return nil 63 | } 64 | } 65 | 66 | /** 67 | Initialize an instance given a JSON file contained within the bundle. 68 | 69 | - parameter bundle: The bundle to attempt to load from. 70 | - parameter string: A string containing the name of the file to load from resources. 71 | */ 72 | public init?(bundleClass: AnyClass, filename: String) { 73 | let bundle = Bundle(for: bundleClass) 74 | self.init(bundle: bundle, filename: filename) 75 | } 76 | 77 | public init?(bundle: Bundle, filename: String) { 78 | let filepath: String? = bundle.path(forResource: filename, ofType: nil) 79 | if let filepath = filepath { 80 | self.init(path: filepath) 81 | } else { 82 | return nil 83 | } 84 | } 85 | 86 | /** 87 | If the object in question is a dictionary, this will return the value of the key at the specified index. 88 | If the object is an array, it will return the value at the specified index. 89 | 90 | This subscript is currently readonly. 91 | */ 92 | public subscript(index: Int) -> JSON? { 93 | get { 94 | /** 95 | NSDictionary is used because it currently performs better than a native Swift dictionary. 96 | The reason for this is that [String : Any] is bridged to NSDictionary deep down the 97 | call stack, and this bridging operation is relatively expensive. Until Swift is ABI stable 98 | and/or doesn't require a bridge to Objective-C, NSDictionary will be used here 99 | */ 100 | if let dictionary = object as? NSDictionary { 101 | if let keys = dictionary.allKeys as? [String] { 102 | let key = keys[index] 103 | let value = dictionary[key] 104 | if let value = value { 105 | return JSON(value) 106 | } 107 | } 108 | } else if let array = object as? NSArray { 109 | let value = array[index] 110 | return JSON(value) 111 | } 112 | 113 | return nil 114 | } 115 | } 116 | 117 | /** 118 | Returns or sets the key to a given value. 119 | */ 120 | public subscript(key: String) -> JSON? { 121 | set { 122 | if var tempObject = object as? [String : Any] { 123 | tempObject[key] = newValue?.object 124 | self.object = tempObject 125 | } 126 | else { 127 | var tempObject: [String : Any] = [:] 128 | tempObject[key] = newValue?.object 129 | self.object = tempObject 130 | } 131 | } 132 | get { 133 | /** 134 | NSDictionary is used because it currently performs better than a native Swift dictionary. 135 | The reason for this is that [String : Any] is bridged to NSDictionary deep down the 136 | call stack, and this bridging operation is relatively expensive. Until Swift is ABI stable 137 | and/or doesn't require a bridge to Objective-C, NSDictionary will be used here 138 | */ 139 | if let dictionary = object as? NSDictionary { 140 | let value = dictionary[key] 141 | if let value = value { 142 | return JSON(value) 143 | } 144 | } 145 | 146 | return nil 147 | } 148 | } 149 | 150 | public func data() -> Data? { 151 | if let object = object { 152 | return try? JSONSerialization.data(withJSONObject: object, options: .prettyPrinted) 153 | } 154 | return nil 155 | } 156 | 157 | // MARK: - Types (Debugging) 158 | public var type: JSONType { 159 | if let object = object { 160 | switch object { 161 | case is NSString: 162 | return .string 163 | case is NSArray: 164 | return .array 165 | case is NSDictionary: 166 | return .dictionary 167 | case is NSNumber: 168 | let number = object as! NSNumber 169 | let type = String(cString: number.objCType) 170 | // there's no such thing as a 'char' in json, but that's 171 | // what the serializer types it as. 172 | if type == "c" { 173 | return .bool 174 | } 175 | return .number 176 | case is NSNull: 177 | return .null 178 | default: 179 | return .unknown 180 | } 181 | } else { 182 | return .unknown 183 | } 184 | } 185 | 186 | public var objectType: String { 187 | if let object = object { 188 | return "\(Swift.type(of: (object) as AnyObject))" 189 | } else { 190 | return "Unknown" 191 | } 192 | } 193 | 194 | // MARK: - String 195 | public var string: String? { 196 | if let object = object { 197 | var value: String? = nil 198 | switch object { 199 | case is String: 200 | value = object as? String 201 | case is NSDecimalNumber: 202 | value = (object as? NSDecimalNumber)?.stringValue 203 | case is NSNumber: 204 | value = (object as? NSNumber)?.stringValue 205 | default: 206 | break 207 | } 208 | 209 | return value 210 | } else { 211 | return nil 212 | } 213 | } 214 | 215 | // MARK: - NSNumber 216 | public var number: NSNumber? { 217 | if let object = object { 218 | var value: NSNumber? = nil 219 | switch object { 220 | case is NSNumber: 221 | value = object as? NSNumber 222 | case is String: 223 | value = NSDecimalNumber(string: object as? String) 224 | default: 225 | break 226 | } 227 | 228 | return value 229 | } else { 230 | return nil 231 | } 232 | } 233 | 234 | // MARK: - NSDecimalNumber 235 | public var decimal: NSDecimalNumber? { 236 | if let object = object { 237 | var value: NSDecimalNumber? = nil 238 | switch object { 239 | case is String: 240 | let stringValue = object as? String 241 | if let stringValue = stringValue { 242 | value = NSDecimalNumber(string: stringValue) 243 | } 244 | 245 | case is NSDecimalNumber: 246 | value = object as? NSDecimalNumber 247 | 248 | case is NSNumber: 249 | // We need to jump through some hoops here. NSNumber's decimalValue doesn't guarantee 250 | // exactness for float and double types. See "decimalValue" on NSNumber. 251 | let number = object as! NSNumber 252 | let type = String(cString: number.objCType) 253 | 254 | // type encodings can be found here: 255 | // https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html 256 | 257 | switch(type) { 258 | // treat the integer based ones the same and just use 259 | // the largest type. No worries here about rounding. 260 | case "c", "i", "s", "l", "q": 261 | value = NSDecimalNumber(value: number.int64Value as Int64) 262 | break 263 | // do the same with the unsigned types. 264 | case "C", "I", "S", "L", "Q": 265 | value = NSDecimalNumber(value: number.uint64Value as UInt64) 266 | break 267 | // and again with precision types. 268 | case "f", "d": 269 | value = NSDecimalNumber(value: number.doubleValue as Double) 270 | // not sure if we need to handle this, but just in case. 271 | // it shouldn't hurt anything. 272 | case "*": 273 | value = NSDecimalNumber(string: number.stringValue) 274 | // probably don't need this one either, but oh well. 275 | case "B": 276 | value = NSDecimalNumber(value: number.boolValue as Bool) 277 | 278 | default: 279 | break 280 | } 281 | 282 | default: 283 | break 284 | } 285 | 286 | return value 287 | } else { 288 | return nil 289 | } 290 | } 291 | 292 | // MARK: - Float 293 | public var float: Float? { 294 | if let object = object { 295 | var value: Float? = nil 296 | switch object { 297 | case is NSNumber: 298 | value = (object as? NSNumber)?.floatValue 299 | case is String: 300 | let stringValue = object as? String 301 | if let stringValue = stringValue { 302 | value = NSDecimalNumber(string: stringValue).floatValue 303 | } 304 | default: 305 | break; 306 | } 307 | 308 | return value 309 | } else { 310 | return nil 311 | } 312 | } 313 | 314 | // MARK: - Double 315 | public var double: Double? { 316 | if let object = object { 317 | var value: Double? = nil 318 | switch object { 319 | case is NSNumber: 320 | value = (object as? NSNumber)?.doubleValue 321 | case is String: 322 | let stringValue = object as? String 323 | if let stringValue = stringValue { 324 | value = NSDecimalNumber(string: stringValue).doubleValue 325 | } 326 | default: 327 | break; 328 | } 329 | 330 | return value 331 | } else { 332 | return nil 333 | } 334 | } 335 | 336 | // MARK: - Int 337 | public var int: Int? { 338 | if let object = object { 339 | var value: Int? = nil 340 | switch object { 341 | case is NSNumber: 342 | value = (object as? NSNumber)?.intValue 343 | case is String: 344 | let stringValue = object as? String 345 | if let stringValue = stringValue { 346 | value = NSDecimalNumber(string: stringValue).intValue 347 | } 348 | default: 349 | break; 350 | } 351 | 352 | return value 353 | } else { 354 | return nil 355 | } 356 | } 357 | 358 | public var int64: Int64? { 359 | if let object = object { 360 | var value: Int64? = nil 361 | switch object { 362 | case is NSNumber: 363 | value = (object as? NSNumber)?.int64Value 364 | case is String: 365 | let stringValue = object as? String 366 | if let stringValue = stringValue { 367 | value = NSDecimalNumber(string: stringValue).int64Value 368 | } 369 | default: 370 | break; 371 | } 372 | 373 | return value 374 | } else { 375 | return nil 376 | } 377 | } 378 | 379 | // MARK: - UInt 380 | public var uInt: UInt? { 381 | if let object = object { 382 | var value: UInt? = nil 383 | switch object { 384 | case is NSNumber: 385 | value = (object as? NSNumber)?.uintValue 386 | case is String: 387 | let stringValue = object as? String 388 | if let stringValue = stringValue { 389 | value = NSDecimalNumber(string: stringValue).uintValue 390 | } 391 | default: 392 | break; 393 | } 394 | 395 | return value 396 | } else { 397 | return nil 398 | } 399 | } 400 | 401 | public var uInt64: UInt64? { 402 | if let object = object { 403 | var value: UInt64? = nil 404 | switch object { 405 | case is NSNumber: 406 | value = (object as? NSNumber)?.uint64Value 407 | case is String: 408 | let stringValue = object as? String 409 | if let stringValue = stringValue { 410 | value = NSDecimalNumber(string: stringValue).uint64Value 411 | } 412 | default: 413 | break; 414 | } 415 | 416 | return value 417 | } else { 418 | return nil 419 | } 420 | } 421 | 422 | // MARK: - Bool 423 | public var bool: Bool? { 424 | if let object = object { 425 | var value: Bool? = nil 426 | switch object { 427 | case is NSNumber: 428 | value = (object as? NSNumber)?.boolValue 429 | case is String: 430 | let stringValue = object as? String 431 | if let stringValue = stringValue { 432 | value = NSDecimalNumber(string: stringValue).boolValue 433 | } 434 | default: 435 | break; 436 | } 437 | 438 | return value 439 | } else { 440 | return nil 441 | } 442 | } 443 | 444 | // MARK: - NSURL 445 | public var URL: Foundation.URL? { 446 | if let urlString = string { 447 | return Foundation.URL(string: urlString) 448 | } 449 | return nil 450 | } 451 | 452 | // MARK: - Array 453 | public var array: [JSON]? { 454 | if let array = object as? [Any] { 455 | return array.map { JSON($0) } 456 | } 457 | return nil 458 | } 459 | //public var arrayValue: [JSON] { return array ?? [] } 460 | 461 | 462 | // MARK: - Dictionary 463 | public var dictionary: [String : JSON]? { 464 | if let dictionary = object as? [String : Any] { 465 | return Dictionary(dictionary.map { ($0, JSON($1)) }) 466 | } 467 | return nil 468 | } 469 | //public var dictionaryValue: [String : JSON] { return dictionary ?? [:] } 470 | } 471 | 472 | extension Dictionary { 473 | fileprivate init(_ pairs: [Element]) { 474 | self.init() 475 | for (key, value) in pairs { 476 | self[key] = value 477 | } 478 | } 479 | } 480 | 481 | // MARK: - Operators 482 | 483 | public func ==(lhs: JSON, rhs: JSON) -> Bool { 484 | if let lhsObject: Any = lhs.object, let rhsObject: Any = rhs.object { 485 | switch (lhsObject, rhsObject) { 486 | case (let left as String, let right as String): 487 | return left == right 488 | case (let left as Double, let right as Double): 489 | return left == right 490 | case (let left as Float, let right as Float): 491 | return left == right 492 | case (let left as Int, let right as Int): 493 | return left == right 494 | case (let left as Int64, let right as Int64): 495 | return left == right 496 | case (let left as UInt, let right as UInt): 497 | return left == right 498 | case (let left as UInt64, let right as UInt64): 499 | return left == right 500 | case (let left as Bool, let right as Bool): 501 | return left == right 502 | case (let left as [Any], let right as [Any]): 503 | return left.map { JSON($0) } == right.map { JSON ($0) } 504 | case (let left as [String : Any], let right as [String : Any]): 505 | return Dictionary(left.map { ($0, JSON($1)) }) == Dictionary(right.map { ($0, JSON($1)) }) 506 | default: return false 507 | } 508 | } 509 | 510 | return false 511 | } 512 | 513 | // MARK: - CustomStringConvertible 514 | 515 | extension JSON: CustomStringConvertible { 516 | public var description: String { 517 | if let object: Any = object { 518 | switch object { 519 | case is String, is NSNumber, is Float, is Double, is Int, is UInt, is Bool: return "\(object)" 520 | case is [Any], is [String : Any]: 521 | if let data = try? JSONSerialization.data(withJSONObject: object, options: .prettyPrinted) { 522 | return NSString(data: data, encoding: String.Encoding.utf8.rawValue) as String? ?? "" 523 | } 524 | default: return "" 525 | } 526 | } 527 | 528 | return "\(String(describing: object))" 529 | } 530 | } 531 | 532 | // MARK: - CustomDebugStringConvertible 533 | 534 | extension JSON: CustomDebugStringConvertible { 535 | public var debugDescription: String { 536 | return description 537 | } 538 | } 539 | 540 | // MARK: - NilLiteralConvertible 541 | 542 | extension JSON: ExpressibleByNilLiteral { 543 | public init(nilLiteral: ()) { 544 | self.init() 545 | } 546 | } 547 | 548 | // MARK: - StringLiteralConvertible 549 | 550 | extension JSON: ExpressibleByStringLiteral { 551 | public init(stringLiteral value: StringLiteralType) { 552 | self.init(value) 553 | } 554 | 555 | public init(extendedGraphemeClusterLiteral value: StringLiteralType) { 556 | self.init(value) 557 | } 558 | 559 | public init(unicodeScalarLiteral value: StringLiteralType) { 560 | self.init(value) 561 | } 562 | } 563 | 564 | // MARK: - FloatLiteralConvertible 565 | 566 | extension JSON: ExpressibleByFloatLiteral { 567 | public init(floatLiteral value: FloatLiteralType) { 568 | self.init(value) 569 | } 570 | } 571 | 572 | // MARK: - IntegerLiteralConvertible 573 | 574 | extension JSON: ExpressibleByIntegerLiteral { 575 | public init(integerLiteral value: IntegerLiteralType) { 576 | self.init(value) 577 | } 578 | } 579 | 580 | // MARK: - BooleanLiteralConvertible 581 | 582 | extension JSON: ExpressibleByBooleanLiteral { 583 | public init(booleanLiteral value: BooleanLiteralType) { 584 | self.init(value) 585 | } 586 | } 587 | 588 | // MARK: - ArrayLiteralConvertible 589 | 590 | extension JSON: ExpressibleByArrayLiteral { 591 | public init(arrayLiteral elements: Any...) { 592 | self.init(elements) 593 | } 594 | } 595 | 596 | // MARK: - DictionaryLiteralConvertible 597 | 598 | extension JSON: ExpressibleByDictionaryLiteral { 599 | public init(dictionaryLiteral elements: (String, Any)...) { 600 | var object: [String : Any] = [:] 601 | 602 | for (key, value) in elements { 603 | object[key] = value 604 | } 605 | 606 | self.init(object) 607 | } 608 | } 609 | 610 | 611 | 612 | 613 | 614 | -------------------------------------------------------------------------------- /ELCodableTests/DecimalTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DecimalTests.swift 3 | // ELCodable 4 | // 5 | // Created by Brandon Sneed on 1/15/16. 6 | // Copyright © 2016 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ELCodable 11 | 12 | class DecimalTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testEquality() { 25 | let doubleValue: Double = 264.91 26 | let jsonValue = JSON(doubleValue) 27 | 28 | let subtotal = Decimal(jsonValue.decimal!) 29 | 30 | XCTAssertEqual(subtotal, Decimal(doubleValue)) 31 | } 32 | 33 | } 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /ELCodableTests/DynamicKeyTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicKeyTest.swift 3 | // ELCodable 4 | // 5 | // Created by Brandon Sneed on 7/21/16. 6 | // Copyright © 2016 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ELCodable 11 | 12 | struct MyData { 13 | let availableInStore: Int 14 | let format: String 15 | let identifier: String 16 | let location: LocationData 17 | let name: String 18 | let packagePrice: ELCodable.Decimal 19 | let unitPrice: ELCodable.Decimal 20 | } 21 | 22 | extension MyData: ELCodable.Decodable { 23 | static func decode(_ json: JSON?) throws -> MyData { 24 | let buriedJson = json?["data"]?[0] 25 | 26 | return try MyData( 27 | availableInStore: buriedJson ==> "availabilityInStore", 28 | format: buriedJson ==> "format", 29 | identifier: buriedJson ==> "identifier", 30 | location: buriedJson ==> "location", 31 | name: buriedJson ==> "name", 32 | packagePrice: buriedJson ==> "packagePrice", 33 | unitPrice: buriedJson ==> "unitPrice" 34 | ) 35 | } 36 | } 37 | 38 | struct LocationData { 39 | let aisle: String 40 | let section: String 41 | let zone: String 42 | } 43 | 44 | extension LocationData: ELCodable.Decodable { 45 | static func decode(_ json: JSON?) throws -> LocationData { 46 | return try LocationData( 47 | aisle: json ==> "aisle", 48 | section: json ==> "section", 49 | zone: json ==> "zone" 50 | ) 51 | } 52 | } 53 | 54 | 55 | 56 | class DynamicKeyTest: XCTestCase { 57 | 58 | override func setUp() { 59 | super.setUp() 60 | // Put setup code here. This method is called before the invocation of each test method in the class. 61 | } 62 | 63 | override func tearDown() { 64 | // Put teardown code here. This method is called after the invocation of each test method in the class. 65 | super.tearDown() 66 | } 67 | 68 | func testRandomKeyExtraction() { 69 | guard let json = JSON(bundleClass: ELCodableTests.self, filename: "DynamicKeyedData.json") else { 70 | assertionFailure("the json is missing.") 71 | return 72 | } 73 | 74 | var thrownError: Error? = nil 75 | 76 | do { 77 | let model = try MyData.decode(json) 78 | XCTAssertTrue(model.availableInStore == 15) 79 | XCTAssertTrue(model.format == "EAN13") 80 | XCTAssertTrue(model.location.zone == "A") 81 | XCTAssertTrue(model.unitPrice == Decimal(3.32)) 82 | } catch let error { 83 | thrownError = error 84 | } 85 | 86 | XCTAssertTrue(thrownError == nil) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /ELCodableTests/DynamicKeyedData.json: -------------------------------------------------------------------------------- 1 | { 2 | "apiVersion": "v1", 3 | "data": { 4 | "5260": { 5 | "availabilityInStore": 15, 6 | "format": "EAN13", 7 | "identifier": "0078742079905", 8 | "location": { 9 | "aisle": "3", 10 | "section": "20", 11 | "zone": "A" 12 | }, 13 | "name": "GV N-STIR CRMY 26.5Z", 14 | "packagePrice": 3.32, 15 | "unitPrice": 3.32 16 | } 17 | }, 18 | "meta": { 19 | "isExtruded": true, 20 | "pluginVersion": "v1.0.0" 21 | } 22 | } -------------------------------------------------------------------------------- /ELCodableTests/ELCodableTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ELCodableTests.swift 3 | // ELCodableTests 4 | // 5 | // Created by Brandon Sneed on 11/12/15. 6 | // Copyright © 2015 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import ELCodable 11 | 12 | struct SubModel { 13 | let aSubString: String 14 | } 15 | 16 | extension SubModel: ELCodable.Decodable { 17 | static func decode(_ json: JSON?) throws -> SubModel { 18 | return try SubModel( 19 | aSubString: json ==> "aSubString" 20 | ) 21 | } 22 | } 23 | 24 | extension SubModel: ELCodable.Encodable { 25 | func encode() throws -> JSON { 26 | return try encodeToJSON([ 27 | "aSubString1" <== aSubString 28 | ]) 29 | } 30 | } 31 | 32 | struct TestModel { 33 | let aString: String 34 | let aFloat: Float 35 | let anInt: Int 36 | let aNumber: ELCodable.Decimal 37 | let anArray: [String] 38 | let aModel: SubModel 39 | let aModelArray: [SubModel] 40 | 41 | let optString: String? 42 | let optStringNil: Int? 43 | let optModel: SubModel? 44 | let optModelNil: SubModel? 45 | let optModelArray: [SubModel]? 46 | let optModelArrayNil: [SubModel]? 47 | } 48 | 49 | extension TestModel: ELCodable.Decodable { 50 | static func decode(_ json: JSON?) throws -> TestModel { 51 | return try TestModel( 52 | aString: json ==> "aString", 53 | aFloat: json ==> "aFloat", 54 | anInt: json ==> "anInt", 55 | aNumber: json ==> "aNumber", 56 | anArray: json ==> "anArray", 57 | aModel: json ==> "aModel", 58 | aModelArray: json ==> "aModelArray", 59 | optString: json ==> "optString", 60 | optStringNil: json ==> "optStringNil", 61 | optModel: json ==> "optModel", 62 | optModelNil: json ==> "optModelNil", 63 | optModelArray: json ==> "optModelArray", 64 | optModelArrayNil: json ==> "optModelArrayNil" 65 | ).validateDecode() 66 | } 67 | 68 | func validateDecode() throws -> TestModel { 69 | if aFloat == 1.234 { 70 | return self 71 | } else { 72 | throw DecodeError.validationFailed 73 | } 74 | } 75 | } 76 | 77 | extension TestModel: ELCodable.Encodable { 78 | func encode() throws -> JSON { 79 | return try validateEncode().encodeToJSON([ 80 | "aString1" <== aString, 81 | "aFloat1" <== aFloat, 82 | "anInt1" <== anInt, 83 | "aNumber1" <== aNumber, 84 | "anArray1" <== anArray, 85 | "aModel1" <== aModel, 86 | "aModelArray1" <== aModelArray, 87 | "alwaysNull" <== NSNull() 88 | ]) 89 | } 90 | 91 | func validateEncode() throws -> TestModel { 92 | return self 93 | } 94 | } 95 | 96 | class ELCodableTests: XCTestCase { 97 | 98 | override func setUp() { 99 | super.setUp() 100 | // Put setup code here. This method is called before the invocation of each test method in the class. 101 | } 102 | 103 | override func tearDown() { 104 | // Put teardown code here. This method is called after the invocation of each test method in the class. 105 | super.tearDown() 106 | } 107 | 108 | func testExample() { 109 | // This is an example of a functional test case. 110 | // Use XCTAssert and related functions to verify your tests produce the correct results. 111 | } 112 | 113 | func testPerformanceExample() { 114 | // This is an example of a performance test case. 115 | self.measure { 116 | // Put the code you want to measure the time of here. 117 | } 118 | } 119 | 120 | func testDecode() { 121 | var json = JSON() 122 | 123 | json["aString"] = "hello" 124 | json["aFloat"] = 1.234 125 | json["anInt"] = 1234 126 | json["aNumber"] = 1234 127 | json["anArray"] = ["1", "2", "3", "4"] 128 | json["aModel"] = JSON(["aSubString": "value"]) 129 | json["aModelArray"] = JSON([["aSubString": "value1"], ["aSubString": "value2"], ["aSubString": "value3"]]) 130 | 131 | // optional tests 132 | 133 | json["optString"] = JSON("helloAgain") 134 | json["optStringNil"] = JSON() 135 | json["optModel"] = ["aSubString": "value"] 136 | json["optModelArray"] = JSON([["aSubString": "value1"], ["aSubString": "value2"], ["aSubString": "value3"]]) 137 | 138 | let model = try? TestModel.decode(json) 139 | print(model as Any) 140 | 141 | let output = ((try? model?.encode()) as JSON??) 142 | print(output as Any) 143 | } 144 | 145 | func testDecodeThrowEmptyJSON() { 146 | var thrown = false 147 | 148 | do { 149 | let model = try TestModel.decode(nil) 150 | print(model) 151 | } catch DecodeError.emptyJSON { 152 | thrown = true 153 | } catch { 154 | thrown = false 155 | } 156 | 157 | XCTAssert(thrown, ".EmptyJSON error was not thrown!") 158 | } 159 | 160 | func testDecodeThrowNotFound() { 161 | var thrown = false 162 | var thrownKey: String? = nil 163 | 164 | do { 165 | var json = JSON() 166 | json["blah"] = 1 167 | 168 | // first key it'll hit is "aString", which should be missing. 169 | let model = try TestModel.decode(json) 170 | print(model) 171 | } catch DecodeError.notFound(let key) { 172 | thrown = true 173 | thrownKey = key 174 | } catch { 175 | thrown = false 176 | } 177 | 178 | XCTAssert(thrown, ".NotFound error was not thrown!") 179 | XCTAssert(thrownKey == "aString", "The .NotFound key value isn't right!") 180 | } 181 | 182 | func testNonOptionalValue() { 183 | var json = JSON() 184 | var thrown = false 185 | var thrownKey: String? = nil 186 | 187 | // remove aString and watch it fail. 188 | //json["aString"] = "hello" 189 | json["aFloat"] = 1.234 190 | json["anInt"] = 1234 191 | json["aNumber"] = 1234 192 | json["anArray"] = ["1", "2", "3", "4"] 193 | json["aModel"] = JSON(["aSubString": "value"]) 194 | json["aModelArray"] = JSON([["aSubString": "value1"], ["aSubString": "value2"], ["aSubString": "value3"]]) 195 | 196 | // optional tests 197 | 198 | json["optString"] = JSON("helloAgain") 199 | json["optStringNil"] = JSON() 200 | json["optModel"] = ["aSubString": "value"] 201 | json["optModelArray"] = JSON([["aSubString": "value1"], ["aSubString": "value2"], ["aSubString": "value3"]]) 202 | 203 | do { 204 | let model = try TestModel.decode(json) 205 | print(model) 206 | } catch DecodeError.notFound(let key) { 207 | thrown = true 208 | thrownKey = key 209 | } catch { 210 | thrown = false 211 | } 212 | 213 | XCTAssert(thrown, ".NotFound error was not thrown!") 214 | XCTAssert(thrownKey == "aString", "The .NotFound key value isn't right!") 215 | } 216 | 217 | func testOptionalValue() { 218 | var json = JSON() 219 | var thrown = false 220 | 221 | json["aString"] = "hello" 222 | json["aFloat"] = 1.234 223 | json["anInt"] = 1234 224 | json["aNumber"] = 1234 225 | json["anArray"] = ["1", "2", "3", "4"] 226 | json["aModel"] = JSON(["aSubString": "value"]) 227 | json["aModelArray"] = JSON([["aSubString": "value1"], ["aSubString": "value2"], ["aSubString": "value3"]]) 228 | 229 | // optional tests 230 | 231 | // remove optString and it should still pass. 232 | //json["optString"] = JSON("helloAgain") 233 | json["optStringNil"] = JSON() 234 | json["optModel"] = ["aSubString": "value"] 235 | json["optModelArray"] = JSON([["aSubString": "value1"], ["aSubString": "value2"], ["aSubString": "value3"]]) 236 | 237 | do { 238 | let model = try TestModel.decode(json) 239 | print(model) 240 | } catch { 241 | thrown = true 242 | } 243 | 244 | XCTAssert(thrown == false, "An error was thrown for optString and it shouldn't have been!") 245 | } 246 | 247 | func testArrayModelValueFailure() { 248 | var json = JSON() 249 | var thrown = false 250 | var thrownKey: String? = nil 251 | 252 | json["aString"] = "hello" 253 | json["aFloat"] = 1.234 254 | json["anInt"] = 1234 255 | json["aNumber"] = 1234 256 | json["anArray"] = ["1", "2", "3", "4"] 257 | json["aModel"] = JSON(["aSubString": "value"]) 258 | json["aModelArray"] = JSON([["SomeString": "value1"], ["aSubString": "value2"], ["aSubString": "value3"]]) 259 | 260 | // optional tests 261 | 262 | // remove optString and it should still pass. 263 | json["optString"] = JSON("helloAgain") 264 | json["optStringNil"] = JSON() 265 | json["optModel"] = ["aSubString": "value"] 266 | json["optModelArray"] = JSON([["aSubString": "value1"], ["aSubString": "value2"], ["aSubString": "value3"]]) 267 | 268 | do { 269 | let model = try TestModel.decode(json) 270 | print(model) 271 | } catch DecodeError.notFound(let key) { 272 | thrown = true 273 | thrownKey = key 274 | } catch { 275 | thrown = true 276 | } 277 | 278 | XCTAssert(thrown == true, "An error wasn't thrown!") 279 | XCTAssert(thrownKey == "aSubString", "The .NotFound key value isn't right!") 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /ELCodableTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ELCodableTests/JSONTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JSONTests.swift 3 | // Codable 4 | // 5 | // Created by Brandon Sneed on 10/27/15. 6 | // Copyright © 2015 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import ELCodable 11 | 12 | class JSONTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testReadingFromJSON() { 25 | let json = JSON(bundleClass: ELCodableTests.self, filename: "jsontest_models.json") 26 | 27 | // types 28 | /* 29 | case Number 30 | case String 31 | case Bool 32 | case Array 33 | case Dictionary 34 | case Null 35 | case Unknown 36 | */ 37 | 38 | XCTAssertTrue(json?["mystring"]?.type == .string) 39 | XCTAssertTrue(json?["decimalNumber"]?.type == .number) 40 | XCTAssertTrue(json?["bool"]?.type == .bool) 41 | XCTAssertTrue(json?["double"]?.type == .number) 42 | XCTAssertTrue(json?["int"]?.type == .number) 43 | XCTAssertTrue(json?["myarray1"]?.type == .array) 44 | XCTAssertTrue(json?["mydictionary"]?.type == .dictionary) 45 | XCTAssertTrue(json?["null"]?.type == .null) 46 | } 47 | 48 | func testWritingToJSON() { 49 | let dictData = ["key1": "value1", "key2": 1234] as [String : Any] 50 | let arrayData = ["1", "2", "3", "4"] 51 | let stringData = "true" 52 | let numberData = 123456789 53 | let nullData = NSNull() 54 | 55 | var json = JSON() 56 | json["stringData"] = JSON(stringData) 57 | json["numberData"] = JSON(numberData) 58 | json["arrayData"] = JSON(arrayData) 59 | json["dictData"] = JSON(dictData) 60 | json["nullData"] = JSON(nullData) 61 | 62 | print(json) 63 | } 64 | 65 | func testCollectionStuff() { 66 | let dictData = ["key1": "value1", "key2": 1234] as [String : Any] 67 | let arrayData = ["1", "2", "3", "4"] 68 | let stringData = "true" 69 | let numberData = 123456789 70 | 71 | var json = JSON() 72 | json["stringData"] = JSON(stringData) 73 | json["numberData"] = JSON(numberData) 74 | json["arrayData"] = JSON(arrayData) 75 | json["dictData"] = JSON(dictData) 76 | 77 | XCTAssertTrue(json["arrayData"]!.array! == JSON(arrayData).array!) 78 | XCTAssertTrue(json["dictData"]!.dictionary! == JSON(dictData).dictionary!) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /ELCodableTests/KeyPathTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KeyPathTests.swift 3 | // ELCodable 4 | // 5 | // Created by Brandon Sneed on 3/15/16. 6 | // Copyright © 2016 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ELCodable 11 | 12 | struct VersionModel { 13 | let minVersion: String 14 | let url: String 15 | let version: String 16 | } 17 | 18 | extension VersionModel: ELCodable.Decodable { 19 | static func decode(_ json: JSON?) throws -> VersionModel { 20 | return try VersionModel( 21 | minVersion: json?["appVersion"]?["iOS"] ==> "minVersion", 22 | url: json?["appVersion"]?["iOS"] ==> "url", 23 | version: json?["appVersion"]?["iOS"] ==> "version" 24 | ) 25 | } 26 | } 27 | 28 | class KeyPathTests: XCTestCase { 29 | 30 | override func setUp() { 31 | super.setUp() 32 | // Put setup code here. This method is called before the invocation of each test method in the class. 33 | } 34 | 35 | override func tearDown() { 36 | // Put teardown code here. This method is called after the invocation of each test method in the class. 37 | super.tearDown() 38 | } 39 | 40 | func testUglyKeyPath() { 41 | guard let json = JSON(bundleClass: ELCodableTests.self, filename: "jsontest_models.json") else { 42 | assertionFailure("the json is missing.") 43 | return 44 | } 45 | 46 | var thrownError: Error? = nil 47 | 48 | do { 49 | let model = try VersionModel.decode(json) 50 | XCTAssertTrue(model.minVersion == "0.1.4") 51 | XCTAssertTrue(model.url == "https://walmart.com/change-me") 52 | XCTAssertTrue(model.version == "0.1.4") 53 | } catch let error { 54 | thrownError = error 55 | } 56 | 57 | XCTAssertTrue(thrownError == nil) 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /ELCodableTests/NestedErrorTesting.json: -------------------------------------------------------------------------------- 1 | { 2 | "description" : "Walmart", 3 | "iD" : "2280", 4 | "hoursOfOperation" : [ 5 | { 6 | "day" : "Sun - Sat", 7 | "time" : "07:00AM - 10:00PM" 8 | } 9 | ], 10 | "phone" : "(650) 917-0796", 11 | "storeNumber" : "2280", 12 | "storeType" : "2", 13 | "storeServices" : [ 14 | ], 15 | "longitude" : "-122.10944299", 16 | "storeClosedTemporarily" : "false", 17 | "latitude" : "37.40088999", 18 | "mscoEnabled" : "false", 19 | "rxFiltered" : "false", 20 | "openDate" : "11\/1\/1995", 21 | "address" : { 22 | "registry" : "false", 23 | "country" : "United States", 24 | "state" : "CA", 25 | "city" : "Mountain View", 26 | "street1" : "600 Showers Dr", 27 | "zip" : "94040" 28 | }, 29 | "reOpenDate" : "1\/12\/2016", 30 | "localAdAvailable" : "true", 31 | "availableForS2S" : "true", 32 | "storeOpeningSoon" : "false" 33 | } 34 | -------------------------------------------------------------------------------- /ELCodableTests/NestedErrorTesting.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NestedErrorTesting.swift 3 | // ELCodable 4 | // 5 | // Created by Brandon Sneed on 1/12/16. 6 | // Copyright © 2016 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ELCodable 11 | import CoreLocation 12 | 13 | // MARK: WMSNGAddress 14 | 15 | struct WMSNGAddress: Equatable { 16 | let street1: String 17 | let street2: String? 18 | let city: String 19 | let state: String 20 | let zip: String 21 | let country: String 22 | } 23 | 24 | func ==(lhs: WMSNGAddress, rhs: WMSNGAddress) -> Bool { 25 | return lhs.street1 == rhs.street1 && 26 | lhs.street2 == rhs.street2 && 27 | lhs.city == rhs.city && 28 | lhs.state == rhs.state && 29 | lhs.zip == rhs.zip && 30 | lhs.country == rhs.country 31 | } 32 | 33 | extension WMSNGAddress: ELCodable.Decodable { 34 | static func decode(_ json: JSON?) throws -> WMSNGAddress { 35 | return try WMSNGAddress(street1: json ==> "street1", 36 | street2: json ==> "street2", 37 | city: json ==> "cityjij", 38 | state: json ==> "state", 39 | zip: json ==> "zip", 40 | country: json ==> "country") 41 | } 42 | 43 | func validate() throws -> WMSNGAddress { 44 | // Possibly validate the data here 45 | return self 46 | } 47 | } 48 | 49 | // MARK: WMSNGStore 50 | 51 | struct WMSNGStore: Equatable { 52 | let storeId: String 53 | let location: CLLocation 54 | let phone: String 55 | let description: String 56 | let address: WMSNGAddress 57 | } 58 | 59 | func ==(lhs: WMSNGStore, rhs: WMSNGStore) -> Bool { 60 | return lhs.storeId == rhs.storeId && 61 | lhs.location == rhs.location && 62 | lhs.phone == rhs.phone && 63 | lhs.description == rhs.description && 64 | lhs.address == rhs.address 65 | } 66 | 67 | extension WMSNGStore: ELCodable.Decodable { 68 | static func decode(_ json: JSON?) throws -> WMSNGStore { 69 | let store = try WMSNGStore(storeId: json ==> "storeNumber", 70 | location: CLLocation(latitude: json ==> "latitude", longitude: json ==> "longitude"), 71 | phone: json ==> "phone", 72 | description: json ==> "description", 73 | address: json ==> "address" 74 | ) 75 | return store 76 | } 77 | 78 | func validate() throws -> WMSNGStore { 79 | // Possibly validate the data here 80 | return self 81 | } 82 | } 83 | 84 | class NestedErrorTesting: XCTestCase { 85 | 86 | override func setUp() { 87 | super.setUp() 88 | // Put setup code here. This method is called before the invocation of each test method in the class. 89 | } 90 | 91 | override func tearDown() { 92 | // Put teardown code here. This method is called after the invocation of each test method in the class. 93 | super.tearDown() 94 | } 95 | 96 | func testNestedFailure() { 97 | let json = JSON(bundleClass: NestedErrorTesting.self, filename: "NestedErrorTesting.json") 98 | 99 | do { 100 | let store = try WMSNGStore.decode(json) 101 | print(store) 102 | XCTFail("Expected decode call to throw error") 103 | } catch DecodeError.emptyJSON { 104 | print("JSON was empty.") 105 | } catch DecodeError.notFound(let key) { 106 | XCTAssertEqual("address", key) 107 | } catch _ { 108 | XCTFail("Unexpected error. Expected DecodeError.notFound.") 109 | } 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /ELCodableTests/OptionalTests.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "storeId": 2280, 4 | "items": [ 5 | { 6 | "format": "UPC", 7 | "identifier": "887276062013", 8 | "quantity": 1, 9 | "itemId": 554069138, 10 | "departmentId": 72, 11 | "subCategoryId": 42, 12 | "name": "SAM 55 LED 55J6200", 13 | "normalizedUpc": "88727606201", 14 | "unitPrice": 748, 15 | "upc": "88727606201", 16 | "packagePrice": 748, 17 | "isWeighted": false, 18 | "price": 748, 19 | "isProductFee": false, 20 | "taxRates": { 21 | "tax1": 8.75 22 | }, 23 | "tax": 65.45 24 | }, 25 | { 26 | "format" : "UPC", 27 | "identifier": "0068113180661", 28 | "quantity": 1, 29 | "itemId": 593908, 30 | "departmentId": 72, 31 | "subCategoryId": 85, 32 | "name": "CA RECYCLE FEE", 33 | "normalizedUpc": "68113180661", 34 | "unitPrice": 5, 35 | "upc": "0068113180661", 36 | "packagePrice": 5, 37 | "isWeighted": false, 38 | "price": 5, 39 | "isProductFee": true, 40 | "taxRates": { 41 | "tax12": 0 42 | }, 43 | "tax": 0 44 | } 45 | ], 46 | "subtotal": 748, 47 | "productFees": 5, 48 | "tax": 65.45, 49 | "taxAmounts": { 50 | "tax1": 65.45, 51 | "tax12": 0 52 | }, 53 | "total": 818.45 54 | } 55 | } -------------------------------------------------------------------------------- /ELCodableTests/OptionalTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OptionalTests.swift 3 | // ELCodable 4 | // 5 | // Created by Brandon Sneed on 2/23/16. 6 | // Copyright © 2016 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ELCodable 11 | 12 | struct Data { 13 | var cart: Cart 14 | } 15 | 16 | extension Data: ELCodable.Decodable { 17 | static func decode(_ json: JSON?) throws -> Data { 18 | return try Data( 19 | cart: json ==> "data" 20 | ) 21 | } 22 | } 23 | 24 | struct Cart { 25 | var total: ELCodable.Decimal 26 | var clientTransactionId: String? 27 | var recordSaleTransactionId: String? 28 | var approvalNumber: String? 29 | var authorizerId: String? 30 | } 31 | 32 | extension Cart: ELCodable.Decodable { 33 | static func decode(_ json: JSON?) throws -> Cart { 34 | return try Cart( 35 | total: json ==> "total", 36 | clientTransactionId: json ==> "clientTransactionId", 37 | recordSaleTransactionId: json ==> "recordSaleTransactionId", 38 | approvalNumber: json ==> "approvalNumber", 39 | authorizerId: json ==> "authorizerId" 40 | ) 41 | } 42 | } 43 | 44 | class OptionalTests: XCTestCase { 45 | 46 | override func setUp() { 47 | super.setUp() 48 | // Put setup code here. This method is called before the invocation of each test method in the class. 49 | } 50 | 51 | override func tearDown() { 52 | // Put teardown code here. This method is called after the invocation of each test method in the class. 53 | super.tearDown() 54 | } 55 | 56 | func testBasicOptionals() { 57 | /*guard let json = JSON(bundleClass: ELCodableTests.self, filename: "OptionalTests.json") else { 58 | assertionFailure("the json is missing.") 59 | return 60 | } 61 | 62 | var model: Cart? = nil 63 | 64 | guard let json = JSON(responseJson) else { 65 | 66 | } 67 | 68 | guard let data = json["data"] 69 | 70 | guard let jsonDict = json.object as? NSDictionary else { 71 | assertionFailure("the json is jacked up.") 72 | return 73 | } 74 | 75 | guard let data = jsonDict["data"] as? NSDictionary else { 76 | assertionFailure("the data object is missing") 77 | return 78 | } 79 | 80 | var thrownError: ErrorType? = nil 81 | 82 | do { 83 | model = try Cart.decode(JSON(data)) 84 | } catch let error { 85 | thrownError = error 86 | } 87 | 88 | if thrownError != nil { 89 | print(thrownError) 90 | } 91 | 92 | XCTAssertTrue(model != nil, "Cart model is nil!") 93 | XCTAssertTrue(model?.total == Decimal(818.45), "Total doesn't have the right value!") 94 | XCTAssertTrue(model?.clientTransactionId == nil)*/ 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /ELCodableTests/jsontest_models.json: -------------------------------------------------------------------------------- 1 | { 2 | "mystring": "hello", 3 | "myuint": 1234, 4 | "mynumber": 3.14, 5 | "myarray1": [ 6 | "1", 7 | "2", 8 | "3", 9 | "4" 10 | ], 11 | "myarray2": [ 12 | "1", 13 | "2", 14 | "3", 15 | "4" 16 | ], 17 | "myobject": { 18 | "mystring": "sub-hello" 19 | }, 20 | "myobjectarray": [ 21 | { 22 | "mystring": "value1", 23 | }, 24 | { 25 | "mystring": "value2", 26 | }, 27 | { 28 | "mystring": "value3", 29 | }, 30 | { 31 | "mystring": "value4", 32 | }, 33 | ], 34 | "mydictionary": { 35 | "someItem": { 36 | "mystring": "someItem" 37 | }, 38 | "someOtherItem": { 39 | "mystring": "someOtherItem" 40 | } 41 | }, 42 | "null": null, 43 | "string": "a string", 44 | "stringNumber": "1234", 45 | "bool": true, 46 | "int": -1234, 47 | "int32": -2147483647, 48 | "int64": -9223372036854775807, 49 | "uint": 4294967295, 50 | "uint32": 4294967295, 51 | "uint64": 18446744073709551615, 52 | "float": 0.08251977, 53 | "double": 0.333333333333333314829616256247390992939, 54 | "boolString": "yes", 55 | "intString": "-1234", 56 | "int32String": "-2147483647", 57 | "int64String": "-9223372036854775807", 58 | "uintString": "1234", 59 | "uint32String": "4294967295", 60 | "uint64String": "18446744073709551615", 61 | "floatString": "0.00000011920928955078125", 62 | "doubleString": "0.99999999999999994444444444444444444444333333333333333314829616256247390992939", 63 | "decimalNumber": 3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, 64 | "appVersion": { 65 | "android": { 66 | "minSDK": "5.1", 67 | "minVersion": "0.1.4", 68 | "url": "https://walmart.com/change-me", 69 | "version": "0.1.4" 70 | }, 71 | "iOS": { 72 | "minVersion": "0.1.4", 73 | "url": "https://walmart.com/change-me", 74 | "version": "0.1.4" 75 | } 76 | }, 77 | "storeIdWhitelist": [ 5260 ] 78 | } -------------------------------------------------------------------------------- /ELCodable_osx/ELCodable_osx.h: -------------------------------------------------------------------------------- 1 | // 2 | // ELCodable_osx.h 3 | // ELCodable_osx 4 | // 5 | // Created by Brandon Sneed on 6/16/16. 6 | // Copyright © 2016 WalmartLabs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for ELCodable_osx. 12 | FOUNDATION_EXPORT double ELCodable_osxVersionNumber; 13 | 14 | //! Project version string for ELCodable_osx. 15 | FOUNDATION_EXPORT const unsigned char ELCodable_osxVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /ELCodable_osx/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 3.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSHumanReadableCopyright 24 | Copyright © 2016 WalmartLabs. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /ELCodable_osxTests/ELCodable_osxTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ELCodable_osxTests.swift 3 | // ELCodable_osxTests 4 | // 5 | // Created by Brandon Sneed on 6/16/16. 6 | // Copyright © 2016 WalmartLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import ELCodable_osx 11 | 12 | class ELCodable_osxTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /ELCodable_osxTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2016 Walmart, WalmartLabs, and other Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ELCodable 2 | 3 | [![Build Status](https://travis-ci.org/Electrode-iOS/ELCodable.svg?branch=master)](https://travis-ci.org/Electrode-iOS/ELCodable) 4 | [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 5 | 6 | **Note:** This framework has been deprecated. It is no longer being actively maintained and will not be updated for future versions of Swift or iOS. 7 | 8 | ELCodable, a data model decoding/encoding framework for Swift. Inspired by [Anviking's Decodable](https://github.com/Anviking/Decodable). ELCodable provides a mechanism for decoding and encoding JSON to and from Swift models. 9 | 10 | * Swift optionals to determine required fields from optional fields. 11 | * An easy to use JSON wrapper. 12 | * Encoding to JSON. 13 | * Decoding from JSON. 14 | * Type conversion, both in model types as well as common forms of JSON, such as NSData, Dictionaries, Arrays, etc. 15 | * Data validation. 16 | 17 | ## Requirements 18 | 19 | ELCodable requires Swift 5 and Xcode 10.2 20 | 21 | ## Installation 22 | 23 | ### Carthage 24 | 25 | Install with [Carthage](https://github.com/Carthage/Carthage) by adding the framework to your project's [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile). 26 | 27 | ``` 28 | github "Electrode-iOS/ELCodable" 29 | ``` 30 | 31 | ### Manual 32 | 33 | Install manually by adding `ELCodable.xcodeproj` to your project and configuring your target to link `ELCodable.framework` from `ELCodable` target. 34 | 35 | There are two target that builds `ELCodable.framework`. 36 | 1. `ELCodable`: Creates dynamically linked `ELCodable.framework.` 37 | 2. `ELCodable_static`: Creates statically linked `ELCodable.framework`. 38 | 39 | Both targets build the same product (`ELCodable.framework`), thus linking the same app against both `ELCodable` and `ELCodable_static` should be avoided. 40 | 41 | ## Usage 42 | 43 | ### Defining & using your model 44 | 45 | ```Swift 46 | struct MyModel { 47 | let myString: String 48 | let myNumber: UInt 49 | } 50 | ``` 51 | 52 | Once you've defined your model, now extend it such that it works with the decoder. 53 | 54 | ```Swift 55 | extension MyModel: Decodable { 56 | static func decode(json: JSON?) throws -> MyModel { 57 | return try MyModel( 58 | myString: json ==> "myString", 59 | myNumber: json ==> "myNumber" 60 | ) 61 | } 62 | } 63 | ``` 64 | 65 | The above will allow your model to be decoded. As for triggering decoding, you've got a few options... 66 | 67 | The simplest way: 68 | ```Swift 69 | let myModel = try? MyModel.decode(json) 70 | ``` 71 | 72 | At this point, myModel will either have a value, or be nil. If you'd like more information on what caused a failure, you can do this: 73 | 74 | ```Swift 75 | do { 76 | // decode the json 77 | let myModel = try MyModel.decode(json) 78 | // do something with the model 79 | doSomething(myModel) 80 | } catch DecodeError.NotFound(let key) { 81 | print("MyModel couldn't be decoded because \(key) couldn't be found.") 82 | } catch let error { 83 | // catch all for any errors that may happen. 84 | } 85 | ``` 86 | 87 | Now that we've decoded and done something with our model. Lets look at how encoding would work. 88 | 89 | ### Encoding 90 | 91 | ```Swift 92 | extension MyModel: Encodable { 93 | func encode() throws -> JSON { 94 | return try encodeToJSON( 95 | "myString" <== myString, 96 | "myNumber" <== myNumber 97 | ) 98 | } 99 | } 100 | ``` 101 | 102 | Now that you've done this, you can send it to disk wherever else it might need to go. 103 | 104 | ```Swift 105 | let json = try? myModel.encode() 106 | if let json = json { 107 | json.data().writeToFile(path) 108 | } 109 | ``` 110 | 111 | ### Validation 112 | 113 | Model decode validation is as easy as adding a call to validateModel(), and writing a validateDecode() function. Validating Encoding works more or less the same way. 114 | 115 | ```Swift 116 | extension MyModel: Decodable { 117 | static func decode(json: JSON?) throws -> MyModel { 118 | return try MyModel( 119 | myString: json ==> "myString", 120 | myNumber: json ==> "myNumber" 121 | ).validateModel() // triggers validation to occur 122 | } 123 | 124 | func validateDecode() throws -> MyModel { 125 | if myNumber != 3 { 126 | throw DecodeError.ValidationFailed 127 | } else { 128 | // myNumber is 3, our model is valid. 129 | return self 130 | } 131 | } 132 | } 133 | ``` 134 | ### What about sub-models? 135 | 136 | Take this example model: 137 | 138 | ```Swift 139 | struct TestModel { 140 | let aString: String 141 | let aModelArray: [SubModel] 142 | } 143 | ``` 144 | 145 | As long as SubModel implements Decodable and/or Encodable, it'll "just work". Validation is left up to the implementor, but it's done the same way regardless of sub-models. 146 | 147 | ### What about fields that aren't necessarily required? 148 | 149 | Simply mark them as optionals in your model, like this: 150 | 151 | ```Swift 152 | struct TestModel { 153 | // required 154 | let aString: String 155 | // not required 156 | let aModelArray: [SubModel]? 157 | } 158 | ``` 159 | 160 | ### What types can I use in my models? 161 | 162 | Model types will typically be Swift types. Things like String, UInt, structs, Dictionary, etc. Because of this, it's not suitable for use with Objective-C directly. It can be done though with a little wrapper. See Decimal.swift, which makes NSDecimalNumber a first class type in Swift. 163 | 164 | You may come across other types you'd like to have in your models besides the ones supplied in ELCodable. It's pretty easy to do this, you'd just need to make the type conform to Decodeable and/or Encodable. See below: 165 | 166 | ```Swift 167 | extension Bool: Decodable { 168 | public static func decode(json: JSON?) throws -> Bool { 169 | if let value = json?.bool { 170 | return value 171 | } 172 | throw DecodeError.Undecodable 173 | } 174 | } 175 | 176 | extension Decimal: Decodable { 177 | public static func decode(json: JSON?) throws -> Decimal { 178 | if let value = json?.decimal { 179 | return Decimal(value) 180 | } 181 | throw DecodeError.Undecodable 182 | } 183 | } 184 | ``` 185 | 186 | ### Tell me more about this Decimal type 187 | 188 | The Decimal type allows NSDecimalNumber to work and function exactly as a Double or Float would, while preserving the precision within. There's not much to it really, however since numbers tend to be compared to various things, it implements the Equatable protocol and has various operator overloads on ==, <=, >= etc. 189 | --------------------------------------------------------------------------------