├── .github ├── ISSUE_TEMPLATE.md └── pull_request_template.md ├── .gitignore ├── .travis.yml ├── LICENSE ├── ObjectMapper.podspec ├── ObjectMapper.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ ├── ObjectMapper-Mac.xcscheme │ ├── ObjectMapper-iOS.xcscheme │ ├── ObjectMapper-tvOS.xcscheme │ └── ObjectMapper-watchOS.xcscheme ├── ObjectMapper.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ ├── IDEWorkspaceChecks.plist │ └── ObjectMapper.xcscmblueprint ├── Package.swift ├── Package@swift-4.2.swift ├── Package@swift-4.swift ├── README-CN.md ├── README.md ├── Sources ├── CodableTransform.swift ├── CustomDateFormatTransform.swift ├── DataTransform.swift ├── DateFormatterTransform.swift ├── DateTransform.swift ├── DictionaryTransform.swift ├── EnumOperators.swift ├── EnumTransform.swift ├── FromJSON.swift ├── HexColorTransform.swift ├── ISO8601DateTransform.swift ├── ImmutableMappable.swift ├── Info.plist ├── IntegerOperators.swift ├── Map.swift ├── MapError.swift ├── Mappable.swift ├── Mapper.swift ├── NSDecimalNumberTransform.swift ├── ObjectMapper.h ├── Operators.swift ├── Resources │ └── PrivacyInfo.xcprivacy ├── ToJSON.swift ├── TransformOf.swift ├── TransformOperators.swift ├── TransformType.swift └── URLTransform.swift └── Tests ├── Info.plist └── ObjectMapperTests ├── BasicTypes.swift ├── BasicTypesTestsFromJSON.swift ├── BasicTypesTestsToJSON.swift ├── ClassClusterTests.swift ├── CodableTests.swift ├── CustomTransformTests.swift ├── DataTransformTests.swift ├── DictionaryTransformTests.swift ├── GenericObjectsTests.swift ├── IgnoreNilTests.swift ├── ImmutableTests.swift ├── MapContextTests.swift ├── MappableExtensionsTests.swift ├── MappableTypesWithTransformsTests.swift ├── NSDecimalNumberTransformTests.swift ├── NestedArrayTests.swift ├── NestedKeysTests.swift ├── NullableKeysFromJSONTests.swift ├── ObjectMapperTests.swift ├── PerformanceTests.swift ├── ToObjectTests.swift └── URLTransformTests.swift /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Your JSON dictionary: 2 | 3 | ```json 4 | { 5 | "name": "ObjectMapper", 6 | "url": "https://github.com/Hearst-DD/ObjectMapper" 7 | } 8 | ``` 9 | 10 | ### Your model: 11 | 12 | ```swift 13 | struct Repo: Mappable { 14 | var name: String! 15 | var url: URL! 16 | 17 | init(_ map: Map) { 18 | name <- map["name"] 19 | url <- map["url"] 20 | } 21 | } 22 | ``` 23 | 24 | ### What you did: 25 | 26 | ```swift 27 | let repo = Mapper().map(myJSONDictionary) 28 | ``` 29 | 30 | ### What you expected: 31 | 32 | I exepected something like: 33 | 34 | ```swift 35 | Repo(name: "ObjectMapper", url: "https://github.com/Hearst-DD/ObjectMapper") 36 | ``` 37 | 38 | ### What you got: 39 | 40 | ```swift 41 | Repo(name: "ObjectMapper", url: nil) // expected the url is mapped correctly 42 | ``` 43 | 44 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Why 2 | 3 | 4 | 5 | ## What -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | build/ 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | xcuserdata 12 | *.xccheckout 13 | *.moved-aside 14 | DerivedData 15 | *.xcuserstate 16 | # AppCode etc. 17 | .idea/ 18 | # Desktop Servies 19 | .DS_Store 20 | 21 | # Carthage 22 | Carthage/Build 23 | 24 | # Swift package manager 25 | .build/ 26 | Packages/ 27 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode11.3 3 | 4 | env: 5 | global: 6 | - LANG=en_US.UTF-8 7 | - LC_ALL=en_US.UTF-8 8 | - WORKSPACE="ObjectMapper.xcworkspace" 9 | - IOS_FRAMEWORK_SCHEME="ObjectMapper-iOS" 10 | - OSX_FRAMEWORK_SCHEME="ObjectMapper-Mac" 11 | - TVOS_FRAMEWORK_SCHEME="ObjectMapper-tvOS" 12 | - WATCHOS_FRAMEWORK_SCHEME="ObjectMapper-watchOS" 13 | matrix: 14 | #iOS 15 | - DESTINATION="OS=11.4,name=iPhone X" SCHEME="$IOS_FRAMEWORK_SCHEME" RUN_TESTS="YES" 16 | - DESTINATION="OS=10.3.1,name=iPhone 7 Plus" SCHEME="$IOS_FRAMEWORK_SCHEME" RUN_TESTS="YES" 17 | #macOS 18 | - DESTINATION="arch=x86_64" SCHEME="$OSX_FRAMEWORK_SCHEME" RUN_TESTS="YES" 19 | #tvOS 20 | - DESTINATION="OS=11.4,name=Apple TV 4K" SCHEME="$TVOS_FRAMEWORK_SCHEME" RUN_TESTS="YES" 21 | 22 | before_install: 23 | - gem install xcpretty --no-document --quiet 24 | 25 | script: 26 | - set -o pipefail 27 | - xcodebuild -version 28 | - xcodebuild -showsdks 29 | 30 | # Build Framework in Debug and Run Tests if specified 31 | - if [ $RUN_TESTS == "YES" ]; then 32 | travis_retry xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO test | xcpretty -c; 33 | else 34 | travis_retry xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO build | xcpretty -c; 35 | fi 36 | 37 | # Build Framework in Release and Run Tests if specified 38 | - if [ $RUN_TESTS == "YES" ]; then 39 | travis_retry xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO test | xcpretty -c; 40 | else 41 | travis_retry xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO build | xcpretty -c; 42 | fi 43 | 44 | notifications: 45 | email: false 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2014 Hearst 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /ObjectMapper.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'ObjectMapper' 3 | s.version = '4.4.2' 4 | s.license = 'MIT' 5 | # Ensure developers won't hit CocoaPods/CocoaPods#11402 with the resource 6 | # bundle for the privacy manifest. 7 | s.cocoapods_version = '>= 1.12.0' 8 | s.summary = 'JSON Object mapping written in Swift' 9 | s.homepage = 'https://github.com/tristanhimmelman/ObjectMapper' 10 | s.authors = { 'Tristan Himmelman' => 'tristanhimmelman@gmail.com' } 11 | s.source = { :git => 'https://github.com/tristanhimmelman/ObjectMapper.git', :tag => s.version.to_s } 12 | s.resource_bundle = { 13 | "Privacy" => "Sources/Resources/PrivacyInfo.xcprivacy" 14 | } 15 | s.watchos.deployment_target = '2.0' 16 | s.ios.deployment_target = '13.0' 17 | s.osx.deployment_target = '12.0' 18 | s.tvos.deployment_target = '9.0' 19 | 20 | s.swift_version = '5.0' 21 | 22 | s.requires_arc = true 23 | s.source_files = 'Sources/**/*.swift' 24 | end 25 | -------------------------------------------------------------------------------- /ObjectMapper.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ObjectMapper.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ObjectMapper.xcodeproj/xcshareddata/xcschemes/ObjectMapper-Mac.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 51 | 52 | 53 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 76 | 77 | 83 | 84 | 85 | 86 | 92 | 93 | 99 | 100 | 101 | 102 | 104 | 105 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /ObjectMapper.xcodeproj/xcshareddata/xcschemes/ObjectMapper-iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 51 | 52 | 53 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 76 | 77 | 83 | 84 | 85 | 86 | 92 | 93 | 99 | 100 | 101 | 102 | 104 | 105 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /ObjectMapper.xcodeproj/xcshareddata/xcschemes/ObjectMapper-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 51 | 52 | 62 | 63 | 69 | 70 | 71 | 72 | 78 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /ObjectMapper.xcodeproj/xcshareddata/xcschemes/ObjectMapper-watchOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 51 | 52 | 62 | 63 | 69 | 70 | 71 | 72 | 78 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /ObjectMapper.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ObjectMapper.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ObjectMapper.xcworkspace/xcshareddata/ObjectMapper.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "58AAB0051E2B4EEDF1845A552012E6D0EBAD9127", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | 5 | }, 6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 7 | "58AAB0051E2B4EEDF1845A552012E6D0EBAD9127" : 0, 8 | "95438028B10BBB846574013D29F154A00556A9D1" : 0 9 | }, 10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "A42BB54B-7EE9-41B5-B851-0FC3BB5A9811", 11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 12 | "58AAB0051E2B4EEDF1845A552012E6D0EBAD9127" : "ObjectMapper\/", 13 | "95438028B10BBB846574013D29F154A00556A9D1" : "ObjectMapperCarthage\/Checkouts\/Nimble" 14 | }, 15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "ObjectMapper", 16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "ObjectMapper.xcworkspace", 18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 19 | { 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/Hearst-DD\/ObjectMapper.git", 21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "58AAB0051E2B4EEDF1845A552012E6D0EBAD9127" 23 | }, 24 | { 25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/Quick\/Nimble.git", 26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "95438028B10BBB846574013D29F154A00556A9D1" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.5 2 | 3 | import PackageDescription 4 | 5 | let package = Package(name: "ObjectMapper", 6 | platforms: [.macOS(.v12), 7 | .iOS(.v13), 8 | .tvOS(.v9), 9 | .watchOS(.v2)], 10 | products: [.library(name: "ObjectMapper", 11 | targets: ["ObjectMapper"])], 12 | targets: [.target(name: "ObjectMapper", 13 | path: "Sources"), 14 | .testTarget(name: "ObjectMapperTests", 15 | dependencies: ["ObjectMapper"], 16 | path: "Tests")], 17 | swiftLanguageVersions: [.v5]) 18 | -------------------------------------------------------------------------------- /Package@swift-4.2.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.2 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "ObjectMapper", 8 | products: [ 9 | .library(name: "ObjectMapper", targets: ["ObjectMapper"]), 10 | ], 11 | targets: [ 12 | .target( 13 | name: "ObjectMapper", 14 | path: "Sources" 15 | ) 16 | ], 17 | swiftLanguageVersions: [.v3, .v4, .v4_2] 18 | ) 19 | -------------------------------------------------------------------------------- /Package@swift-4.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "ObjectMapper", 8 | products: [ 9 | .library(name: "ObjectMapper", targets: ["ObjectMapper"]), 10 | ], 11 | targets: [ 12 | .target( 13 | name: "ObjectMapper", 14 | path: "Sources" 15 | ) 16 | ], 17 | swiftLanguageVersions = [3, 4] 18 | ) 19 | -------------------------------------------------------------------------------- /Sources/CodableTransform.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CodableTransform.swift 3 | // ObjectMapper 4 | // 5 | // Created by Jari Kalinainen on 10/10/2018. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | 31 | /// Transforms JSON dictionary to Codable type T and back 32 | open class CodableTransform: TransformType { 33 | 34 | public typealias Object = T 35 | public typealias JSON = Any 36 | 37 | public init() {} 38 | 39 | open func transformFromJSON(_ value: Any?) -> Object? { 40 | var _data: Data? = nil 41 | switch value { 42 | case let dict as [String : Any]: 43 | _data = try? JSONSerialization.data(withJSONObject: dict, options: []) 44 | case let array as [[String : Any]]: 45 | _data = try? JSONSerialization.data(withJSONObject: array, options: []) 46 | default: 47 | _data = nil 48 | } 49 | guard let data = _data else { return nil } 50 | 51 | do { 52 | let decoder = JSONDecoder() 53 | let item = try decoder.decode(T.self, from: data) 54 | return item 55 | } catch { 56 | return nil 57 | } 58 | } 59 | 60 | open func transformToJSON(_ value: T?) -> JSON? { 61 | guard let item = value else { 62 | return nil 63 | } 64 | do { 65 | let encoder = JSONEncoder() 66 | let data = try encoder.encode(item) 67 | let dictionary = try JSONSerialization.jsonObject(with: data, options: .allowFragments) 68 | return dictionary 69 | } catch { 70 | return nil 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Sources/CustomDateFormatTransform.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomDateFormatTransform.swift 3 | // ObjectMapper 4 | // 5 | // Created by Dan McCracken on 3/8/15. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | 31 | open class CustomDateFormatTransform: DateFormatterTransform { 32 | 33 | public init(formatString: String) { 34 | let formatter = DateFormatter() 35 | formatter.locale = Locale(identifier: "en_US_POSIX") 36 | formatter.dateFormat = formatString 37 | 38 | super.init(dateFormatter: formatter) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/DataTransform.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataTransform.swift 3 | // ObjectMapper 4 | // 5 | // Created by Yagrushkin, Evgeny on 8/30/16. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | 31 | open class DataTransform: TransformType { 32 | public typealias Object = Data 33 | public typealias JSON = String 34 | 35 | public init() {} 36 | 37 | open func transformFromJSON(_ value: Any?) -> Data? { 38 | guard let string = value as? String else{ 39 | return nil 40 | } 41 | return Data(base64Encoded: string) 42 | } 43 | 44 | open func transformToJSON(_ value: Data?) -> String? { 45 | guard let data = value else{ 46 | return nil 47 | } 48 | return data.base64EncodedString() 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Sources/DateFormatterTransform.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DateFormatterTransform.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2015-03-09. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | 31 | open class DateFormatterTransform: TransformType { 32 | public typealias Object = Date 33 | public typealias JSON = String 34 | 35 | public let dateFormatter: DateFormatter 36 | 37 | public init(dateFormatter: DateFormatter) { 38 | self.dateFormatter = dateFormatter 39 | } 40 | 41 | open func transformFromJSON(_ value: Any?) -> Date? { 42 | if let dateString = value as? String { 43 | return dateFormatter.date(from: dateString) 44 | } 45 | return nil 46 | } 47 | 48 | open func transformToJSON(_ value: Date?) -> String? { 49 | if let date = value { 50 | return dateFormatter.string(from: date) 51 | } 52 | return nil 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/DateTransform.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DateTransform.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2014-10-13. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | 31 | open class DateTransform: TransformType { 32 | public typealias Object = Date 33 | public typealias JSON = Double 34 | 35 | public enum Unit: TimeInterval { 36 | case seconds = 1 37 | case milliseconds = 1_000 38 | 39 | func addScale(to interval: TimeInterval) -> TimeInterval { 40 | return interval * rawValue 41 | } 42 | 43 | func removeScale(from interval: TimeInterval) -> TimeInterval { 44 | return interval / rawValue 45 | } 46 | } 47 | 48 | private let unit: Unit 49 | 50 | public init(unit: Unit = .seconds) { 51 | self.unit = unit 52 | } 53 | 54 | open func transformFromJSON(_ value: Any?) -> Date? { 55 | var timeInterval: TimeInterval? 56 | if let timeInt = value as? Double { 57 | timeInterval = TimeInterval(timeInt) 58 | } 59 | 60 | if let timeStr = value as? String { 61 | timeInterval = TimeInterval(atof(timeStr)) 62 | } 63 | 64 | return timeInterval.flatMap { 65 | return Date(timeIntervalSince1970: unit.removeScale(from: $0)) 66 | } 67 | } 68 | 69 | open func transformToJSON(_ value: Date?) -> Double? { 70 | if let date = value { 71 | return Double(unit.addScale(to: date.timeIntervalSince1970)) 72 | } 73 | return nil 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Sources/DictionaryTransform.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DictionaryTransform.swift 3 | // ObjectMapper 4 | // 5 | // Created by Milen Halachev on 7/20/16. 6 | // 7 | // Copyright (c) 2014-2018 Tristan Himmelman 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | import Foundation 28 | 29 | ///Transforms [String: AnyObject] <-> [Key: Value] where Key is RawRepresentable as String, Value is Mappable 30 | public struct DictionaryTransform: TransformType where Key: Hashable, Key: RawRepresentable, Key.RawValue == String, Value: Mappable { 31 | 32 | public init() { 33 | 34 | } 35 | 36 | public func transformFromJSON(_ value: Any?) -> [Key: Value]? { 37 | 38 | guard let json = value as? [String: Any] else { 39 | 40 | return nil 41 | } 42 | 43 | let result = json.reduce([:]) { (result, element) -> [Key: Value] in 44 | 45 | guard 46 | let key = Key(rawValue: element.0), 47 | let valueJSON = element.1 as? [String: Any], 48 | let value = Value(JSON: valueJSON) 49 | else { 50 | 51 | return result 52 | } 53 | 54 | var result = result 55 | result[key] = value 56 | return result 57 | } 58 | 59 | return result 60 | } 61 | 62 | public func transformToJSON(_ value: [Key: Value]?) -> Any? { 63 | 64 | let result = value?.reduce([:]) { (result, element) -> [String: Any] in 65 | 66 | let key = element.0.rawValue 67 | let value = element.1.toJSON() 68 | 69 | var result = result 70 | result[key] = value 71 | return result 72 | } 73 | 74 | return result 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Sources/EnumOperators.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EnumOperators.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2016-09-26. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | 31 | 32 | // MARK:- Raw Representable types 33 | 34 | /// Object of Raw Representable type 35 | public func <- (left: inout T, right: Map) { 36 | left <- (right, EnumTransform()) 37 | } 38 | 39 | public func >>> (left: T, right: Map) { 40 | left >>> (right, EnumTransform()) 41 | } 42 | 43 | 44 | /// Optional Object of Raw Representable type 45 | public func <- (left: inout T?, right: Map) { 46 | left <- (right, EnumTransform()) 47 | } 48 | 49 | public func >>> (left: T?, right: Map) { 50 | left >>> (right, EnumTransform()) 51 | } 52 | 53 | 54 | // Code targeting the Swift 4.1 compiler and below. 55 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 56 | /// Implicitly Unwrapped Optional Object of Raw Representable type 57 | public func <- (left: inout T!, right: Map) { 58 | left <- (right, EnumTransform()) 59 | } 60 | #endif 61 | 62 | // MARK:- Arrays of Raw Representable type 63 | 64 | /// Array of Raw Representable object 65 | public func <- (left: inout [T], right: Map) { 66 | left <- (right, EnumTransform()) 67 | } 68 | 69 | public func >>> (left: [T], right: Map) { 70 | left >>> (right, EnumTransform()) 71 | } 72 | 73 | 74 | /// Array of Raw Representable object 75 | public func <- (left: inout [T]?, right: Map) { 76 | left <- (right, EnumTransform()) 77 | } 78 | 79 | public func >>> (left: [T]?, right: Map) { 80 | left >>> (right, EnumTransform()) 81 | } 82 | 83 | 84 | // Code targeting the Swift 4.1 compiler and below. 85 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 86 | /// Array of Raw Representable object 87 | public func <- (left: inout [T]!, right: Map) { 88 | left <- (right, EnumTransform()) 89 | } 90 | #endif 91 | 92 | // MARK:- Dictionaries of Raw Representable type 93 | 94 | /// Dictionary of Raw Representable object 95 | public func <- (left: inout [String: T], right: Map) { 96 | left <- (right, EnumTransform()) 97 | } 98 | 99 | public func >>> (left: [String: T], right: Map) { 100 | left >>> (right, EnumTransform()) 101 | } 102 | 103 | 104 | /// Dictionary of Raw Representable object 105 | public func <- (left: inout [String: T]?, right: Map) { 106 | left <- (right, EnumTransform()) 107 | } 108 | 109 | public func >>> (left: [String: T]?, right: Map) { 110 | left >>> (right, EnumTransform()) 111 | } 112 | 113 | 114 | // Code targeting the Swift 4.1 compiler and below. 115 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 116 | /// Dictionary of Raw Representable object 117 | public func <- (left: inout [String: T]!, right: Map) { 118 | left <- (right, EnumTransform()) 119 | } 120 | #endif 121 | -------------------------------------------------------------------------------- /Sources/EnumTransform.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EnumTransform.swift 3 | // ObjectMapper 4 | // 5 | // Created by Kaan Dedeoglu on 3/20/15. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | 31 | open class EnumTransform: TransformType { 32 | public typealias Object = T 33 | public typealias JSON = T.RawValue 34 | 35 | public init() {} 36 | 37 | open func transformFromJSON(_ value: Any?) -> T? { 38 | if let raw = value as? T.RawValue { 39 | return T(rawValue: raw) 40 | } 41 | return nil 42 | } 43 | 44 | open func transformToJSON(_ value: T?) -> T.RawValue? { 45 | if let obj = value { 46 | return obj.rawValue 47 | } 48 | return nil 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Sources/FromJSON.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FromJSON.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2014-10-09. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2016 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | internal final class FromJSON { 30 | 31 | /// Basic type 32 | class func basicType(_ field: inout FieldType, object: FieldType?) { 33 | if let value = object { 34 | field = value 35 | } 36 | } 37 | 38 | /// optional basic type 39 | class func optionalBasicType(_ field: inout FieldType?, object: FieldType?) { 40 | field = object 41 | } 42 | 43 | // Code targeting the Swift 4.1 compiler and below. 44 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 45 | /// Implicitly unwrapped optional basic type 46 | class func optionalBasicType(_ field: inout FieldType!, object: FieldType?) { 47 | field = object 48 | } 49 | #endif 50 | 51 | /// Mappable object 52 | class func object(_ field: inout N, map: Map) { 53 | if map.toObject { 54 | field = Mapper(context: map.context).map(JSONObject: map.currentValue, toObject: field) 55 | } else if let value: N = Mapper(context: map.context).map(JSONObject: map.currentValue) { 56 | field = value 57 | } 58 | } 59 | 60 | /// Optional Mappable Object 61 | 62 | class func optionalObject(_ field: inout N?, map: Map) { 63 | if let f = field , map.toObject && map.currentValue != nil { 64 | field = Mapper(context: map.context).map(JSONObject: map.currentValue, toObject: f) 65 | } else { 66 | field = Mapper(context: map.context).map(JSONObject: map.currentValue) 67 | } 68 | } 69 | 70 | // Code targeting the Swift 4.1 compiler and below. 71 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 72 | /// Implicitly unwrapped Optional Mappable Object 73 | class func optionalObject(_ field: inout N!, map: Map) { 74 | if let f = field , map.toObject && map.currentValue != nil { 75 | field = Mapper(context: map.context).map(JSONObject: map.currentValue, toObject: f) 76 | } else { 77 | field = Mapper(context: map.context).map(JSONObject: map.currentValue) 78 | } 79 | } 80 | #endif 81 | 82 | /// mappable object array 83 | class func objectArray(_ field: inout Array, map: Map) { 84 | if let objects = Mapper(context: map.context).mapArray(JSONObject: map.currentValue) { 85 | field = objects 86 | } 87 | } 88 | 89 | /// optional mappable object array 90 | 91 | class func optionalObjectArray(_ field: inout Array?, map: Map) { 92 | if let objects: Array = Mapper(context: map.context).mapArray(JSONObject: map.currentValue) { 93 | field = objects 94 | } else { 95 | field = nil 96 | } 97 | } 98 | 99 | // Code targeting the Swift 4.1 compiler and below. 100 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 101 | /// Implicitly unwrapped optional mappable object array 102 | class func optionalObjectArray(_ field: inout Array!, map: Map) { 103 | if let objects: Array = Mapper(context: map.context).mapArray(JSONObject: map.currentValue) { 104 | field = objects 105 | } else { 106 | field = nil 107 | } 108 | } 109 | #endif 110 | 111 | /// mappable object array 112 | class func twoDimensionalObjectArray(_ field: inout Array>, map: Map) { 113 | if let objects = Mapper(context: map.context).mapArrayOfArrays(JSONObject: map.currentValue) { 114 | field = objects 115 | } 116 | } 117 | 118 | /// optional mappable 2 dimentional object array 119 | class func optionalTwoDimensionalObjectArray(_ field: inout Array>?, map: Map) { 120 | field = Mapper(context: map.context).mapArrayOfArrays(JSONObject: map.currentValue) 121 | } 122 | 123 | // Code targeting the Swift 4.1 compiler and below. 124 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 125 | /// Implicitly unwrapped optional 2 dimentional mappable object array 126 | class func optionalTwoDimensionalObjectArray(_ field: inout Array>!, map: Map) { 127 | field = Mapper(context: map.context).mapArrayOfArrays(JSONObject: map.currentValue) 128 | } 129 | #endif 130 | 131 | /// Dctionary containing Mappable objects 132 | class func objectDictionary(_ field: inout Dictionary, map: Map) { 133 | if map.toObject { 134 | field = Mapper(context: map.context).mapDictionary(JSONObject: map.currentValue, toDictionary: field) 135 | } else { 136 | if let objects = Mapper(context: map.context).mapDictionary(JSONObject: map.currentValue) { 137 | field = objects 138 | } 139 | } 140 | } 141 | 142 | /// Optional dictionary containing Mappable objects 143 | class func optionalObjectDictionary(_ field: inout Dictionary?, map: Map) { 144 | if let f = field , map.toObject && map.currentValue != nil { 145 | field = Mapper(context: map.context).mapDictionary(JSONObject: map.currentValue, toDictionary: f) 146 | } else { 147 | field = Mapper(context: map.context).mapDictionary(JSONObject: map.currentValue) 148 | } 149 | } 150 | 151 | // Code targeting the Swift 4.1 compiler and below. 152 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 153 | /// Implicitly unwrapped Dictionary containing Mappable objects 154 | class func optionalObjectDictionary(_ field: inout Dictionary!, map: Map) { 155 | if let f = field , map.toObject && map.currentValue != nil { 156 | field = Mapper(context: map.context).mapDictionary(JSONObject: map.currentValue, toDictionary: f) 157 | } else { 158 | field = Mapper(context: map.context).mapDictionary(JSONObject: map.currentValue) 159 | } 160 | } 161 | #endif 162 | 163 | /// Dictionary containing Array of Mappable objects 164 | class func objectDictionaryOfArrays(_ field: inout Dictionary, map: Map) { 165 | if let objects = Mapper(context: map.context).mapDictionaryOfArrays(JSONObject: map.currentValue) { 166 | field = objects 167 | } 168 | } 169 | 170 | /// Optional Dictionary containing Array of Mappable objects 171 | class func optionalObjectDictionaryOfArrays(_ field: inout Dictionary?, map: Map) { 172 | field = Mapper(context: map.context).mapDictionaryOfArrays(JSONObject: map.currentValue) 173 | } 174 | 175 | // Code targeting the Swift 4.1 compiler and below. 176 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 177 | /// Implicitly unwrapped Dictionary containing Array of Mappable objects 178 | class func optionalObjectDictionaryOfArrays(_ field: inout Dictionary!, map: Map) { 179 | field = Mapper(context: map.context).mapDictionaryOfArrays(JSONObject: map.currentValue) 180 | } 181 | #endif 182 | 183 | /// mappable object Set 184 | class func objectSet(_ field: inout Set, map: Map) { 185 | if let objects = Mapper(context: map.context).mapSet(JSONObject: map.currentValue) { 186 | field = objects 187 | } 188 | } 189 | 190 | /// optional mappable object array 191 | class func optionalObjectSet(_ field: inout Set?, map: Map) { 192 | field = Mapper(context: map.context).mapSet(JSONObject: map.currentValue) 193 | } 194 | 195 | // Code targeting the Swift 4.1 compiler and below. 196 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 197 | /// Implicitly unwrapped optional mappable object array 198 | class func optionalObjectSet(_ field: inout Set!, map: Map) { 199 | field = Mapper(context: map.context).mapSet(JSONObject: map.currentValue) 200 | } 201 | #endif 202 | } 203 | -------------------------------------------------------------------------------- /Sources/HexColorTransform.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HexColorTransform.swift 3 | // ObjectMapper 4 | // 5 | // Created by Vitaliy Kuzmenko on 10/10/16. 6 | // 7 | // Copyright (c) 2014-2018 Tristan Himmelman 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | #if os(iOS) || os(tvOS) || os(watchOS) 28 | import UIKit 29 | #elseif os(macOS) 30 | import Cocoa 31 | #endif 32 | 33 | #if os(iOS) || os(tvOS) || os(watchOS) || os(macOS) 34 | open class HexColorTransform: TransformType { 35 | 36 | #if os(iOS) || os(tvOS) || os(watchOS) 37 | public typealias Object = UIColor 38 | #else 39 | public typealias Object = NSColor 40 | #endif 41 | 42 | public typealias JSON = String 43 | 44 | var prefix: Bool = false 45 | 46 | var alpha: Bool = false 47 | 48 | public init(prefixToJSON: Bool = false, alphaToJSON: Bool = false) { 49 | alpha = alphaToJSON 50 | prefix = prefixToJSON 51 | } 52 | 53 | open func transformFromJSON(_ value: Any?) -> Object? { 54 | if let rgba = value as? String { 55 | if rgba.hasPrefix("#") { 56 | let index = rgba.index(rgba.startIndex, offsetBy: 1) 57 | let hex = String(rgba[index...]) 58 | return getColor(hex: hex) 59 | } else { 60 | return getColor(hex: rgba) 61 | } 62 | } 63 | return nil 64 | } 65 | 66 | open func transformToJSON(_ value: Object?) -> JSON? { 67 | if let value = value { 68 | return hexString(color: value) 69 | } 70 | return nil 71 | } 72 | 73 | fileprivate func hexString(color: Object) -> String { 74 | let comps = color.cgColor.components! 75 | let compsCount = color.cgColor.numberOfComponents 76 | let r: Int 77 | let g: Int 78 | var b: Int 79 | let a = Int(comps[compsCount - 1] * 255) 80 | if compsCount == 4 { // RGBA 81 | r = Int(comps[0] * 255) 82 | g = Int(comps[1] * 255) 83 | b = Int(comps[2] * 255) 84 | } else { // Grayscale 85 | r = Int(comps[0] * 255) 86 | g = Int(comps[0] * 255) 87 | b = Int(comps[0] * 255) 88 | } 89 | var hexString: String = "" 90 | if prefix { 91 | hexString = "#" 92 | } 93 | hexString += String(format: "%02X%02X%02X", r, g, b) 94 | 95 | if alpha { 96 | hexString += String(format: "%02X", a) 97 | } 98 | return hexString 99 | } 100 | 101 | fileprivate func getColor(hex: String) -> Object? { 102 | var red: CGFloat = 0.0 103 | var green: CGFloat = 0.0 104 | var blue: CGFloat = 0.0 105 | var alpha: CGFloat = 1.0 106 | 107 | let scanner = Scanner(string: hex) 108 | var hexValue: CUnsignedLongLong = 0 109 | if scanner.scanHexInt64(&hexValue) { 110 | switch (hex.count) { 111 | case 3: 112 | red = CGFloat((hexValue & 0xF00) >> 8) / 15.0 113 | green = CGFloat((hexValue & 0x0F0) >> 4) / 15.0 114 | blue = CGFloat(hexValue & 0x00F) / 15.0 115 | case 4: 116 | red = CGFloat((hexValue & 0xF000) >> 12) / 15.0 117 | green = CGFloat((hexValue & 0x0F00) >> 8) / 15.0 118 | blue = CGFloat((hexValue & 0x00F0) >> 4) / 15.0 119 | alpha = CGFloat(hexValue & 0x000F) / 15.0 120 | case 6: 121 | red = CGFloat((hexValue & 0xFF0000) >> 16) / 255.0 122 | green = CGFloat((hexValue & 0x00FF00) >> 8) / 255.0 123 | blue = CGFloat(hexValue & 0x0000FF) / 255.0 124 | case 8: 125 | red = CGFloat((hexValue & 0xFF000000) >> 24) / 255.0 126 | green = CGFloat((hexValue & 0x00FF0000) >> 16) / 255.0 127 | blue = CGFloat((hexValue & 0x0000FF00) >> 8) / 255.0 128 | alpha = CGFloat(hexValue & 0x000000FF) / 255.0 129 | default: 130 | // Invalid RGB string, number of characters after '#' should be either 3, 4, 6 or 8 131 | return nil 132 | } 133 | } else { 134 | // "Scan hex error 135 | return nil 136 | } 137 | #if os(iOS) || os(tvOS) || os(watchOS) 138 | return UIColor(red: red, green: green, blue: blue, alpha: alpha) 139 | #else 140 | return NSColor(red: red, green: green, blue: blue, alpha: alpha) 141 | #endif 142 | } 143 | } 144 | #endif 145 | -------------------------------------------------------------------------------- /Sources/ISO8601DateTransform.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ISO8601DateTransform.swift 3 | // ObjectMapper 4 | // 5 | // Created by Jean-Pierre Mouilleseaux on 21 Nov 2014. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | 31 | public extension DateFormatter { 32 | convenience init(withFormat format : String, locale : String) { 33 | self.init() 34 | self.locale = Locale(identifier: locale) 35 | dateFormat = format 36 | } 37 | } 38 | 39 | open class ISO8601DateTransform: DateFormatterTransform { 40 | 41 | static let reusableISODateFormatter = DateFormatter(withFormat: "yyyy-MM-dd'T'HH:mm:ssZZZZZ", locale: "en_US_POSIX") 42 | 43 | public init() { 44 | super.init(dateFormatter: ISO8601DateTransform.reusableISODateFormatter) 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /Sources/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 | 0.14 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Sources/IntegerOperators.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IntegerOperators.swift 3 | // ObjectMapper 4 | // 5 | // Created by Suyeol Jeon on 17/02/2017. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | 31 | // MARK: - Signed Integer 32 | 33 | /// SignedInteger mapping 34 | public func <- (left: inout T, right: Map) { 35 | switch right.mappingType { 36 | case .fromJSON where right.isKeyPresent: 37 | let value: T = toSignedInteger(right.currentValue) ?? 0 38 | FromJSON.basicType(&left, object: value) 39 | case .toJSON: 40 | left >>> right 41 | default: () 42 | } 43 | } 44 | 45 | /// Optional SignedInteger mapping 46 | public func <- (left: inout T?, right: Map) { 47 | switch right.mappingType { 48 | case .fromJSON where right.isKeyPresent: 49 | let value: T? = toSignedInteger(right.currentValue) 50 | FromJSON.basicType(&left, object: value) 51 | case .toJSON: 52 | left >>> right 53 | default: () 54 | } 55 | } 56 | 57 | // Code targeting the Swift 4.1 compiler and below. 58 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 59 | /// ImplicitlyUnwrappedOptional SignedInteger mapping 60 | public func <- (left: inout T!, right: Map) { 61 | switch right.mappingType { 62 | case .fromJSON where right.isKeyPresent: 63 | let value: T! = toSignedInteger(right.currentValue) 64 | FromJSON.basicType(&left, object: value) 65 | case .toJSON: 66 | left >>> right 67 | default: () 68 | } 69 | } 70 | #endif 71 | 72 | 73 | // MARK: - Unsigned Integer 74 | 75 | /// UnsignedInteger mapping 76 | public func <- (left: inout T, right: Map) { 77 | switch right.mappingType { 78 | case .fromJSON where right.isKeyPresent: 79 | let value: T = toUnsignedInteger(right.currentValue) ?? 0 80 | FromJSON.basicType(&left, object: value) 81 | case .toJSON: 82 | left >>> right 83 | default: () 84 | } 85 | } 86 | 87 | 88 | /// Optional UnsignedInteger mapping 89 | public func <- (left: inout T?, right: Map) { 90 | switch right.mappingType { 91 | case .fromJSON where right.isKeyPresent: 92 | let value: T? = toUnsignedInteger(right.currentValue) 93 | FromJSON.basicType(&left, object: value) 94 | case .toJSON: 95 | left >>> right 96 | default: () 97 | } 98 | } 99 | 100 | // Code targeting the Swift 4.1 compiler and below. 101 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 102 | /// ImplicitlyUnwrappedOptional UnsignedInteger mapping 103 | public func <- (left: inout T!, right: Map) { 104 | switch right.mappingType { 105 | case .fromJSON where right.isKeyPresent: 106 | let value: T! = toUnsignedInteger(right.currentValue) 107 | FromJSON.basicType(&left, object: value) 108 | case .toJSON: 109 | left >>> right 110 | default: () 111 | } 112 | } 113 | #endif 114 | 115 | // MARK: - Casting Utils 116 | 117 | /// Convert any value to `SignedInteger`. 118 | private func toSignedInteger(_ value: Any?) -> T? { 119 | guard 120 | let value = value, 121 | case let number as NSNumber = value 122 | else { 123 | return nil 124 | } 125 | 126 | if T.self == Int.self, let x = Int(exactly: number.int64Value) { 127 | return T.init(x) 128 | } 129 | if T.self == Int8.self, let x = Int8(exactly: number.int64Value) { 130 | return T.init(x) 131 | } 132 | if T.self == Int16.self, let x = Int16(exactly: number.int64Value) { 133 | return T.init(x) 134 | } 135 | if T.self == Int32.self, let x = Int32(exactly: number.int64Value) { 136 | return T.init(x) 137 | } 138 | if T.self == Int64.self, let x = Int64(exactly: number.int64Value) { 139 | return T.init(x) 140 | } 141 | 142 | return nil 143 | } 144 | 145 | /// Convert any value to `UnsignedInteger`. 146 | private func toUnsignedInteger(_ value: Any?) -> T? { 147 | guard 148 | let value = value, 149 | case let number as NSNumber = value 150 | else { 151 | return nil 152 | } 153 | 154 | if T.self == UInt.self, let x = UInt(exactly: number.uint64Value) { 155 | return T.init(x) 156 | } 157 | if T.self == UInt8.self, let x = UInt8(exactly: number.uint64Value) { 158 | return T.init(x) 159 | } 160 | if T.self == UInt16.self, let x = UInt16(exactly: number.uint64Value) { 161 | return T.init(x) 162 | } 163 | if T.self == UInt32.self, let x = UInt32(exactly: number.uint64Value) { 164 | return T.init(x) 165 | } 166 | if T.self == UInt64.self, let x = UInt64(exactly: number.uint64Value) { 167 | return T.init(x) 168 | } 169 | 170 | return nil 171 | } 172 | -------------------------------------------------------------------------------- /Sources/Map.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Map.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2015-10-09. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | 30 | import Foundation 31 | 32 | /// MapContext is available for developers who wish to pass information around during the mapping process. 33 | public protocol MapContext { 34 | 35 | } 36 | 37 | /// A class used for holding mapping data 38 | public final class Map { 39 | public let mappingType: MappingType 40 | 41 | public internal(set) var JSON: [String: Any] = [:] 42 | public internal(set) var isKeyPresent = false 43 | public internal(set) var currentValue: Any? 44 | public internal(set) var currentKey: String? 45 | var keyIsNested = false 46 | public internal(set) var nestedKeyDelimiter: String = "." 47 | public var context: MapContext? 48 | public var shouldIncludeNilValues = false /// If this is set to true, toJSON output will include null values for any variables that are not set. 49 | 50 | public let toObject: Bool // indicates whether the mapping is being applied to an existing object 51 | 52 | public init(mappingType: MappingType, JSON: [String: Any], toObject: Bool = false, context: MapContext? = nil, shouldIncludeNilValues: Bool = false) { 53 | 54 | self.mappingType = mappingType 55 | self.JSON = JSON 56 | self.toObject = toObject 57 | self.context = context 58 | self.shouldIncludeNilValues = shouldIncludeNilValues 59 | } 60 | 61 | /// Sets the current mapper value and key. 62 | /// The Key paramater can be a period separated string (ex. "distance.value") to access sub objects. 63 | public subscript(key: String) -> Map { 64 | // save key and value associated to it 65 | return self.subscript(key: key) 66 | } 67 | 68 | public subscript(key: String, delimiter delimiter: String) -> Map { 69 | return self.subscript(key: key, delimiter: delimiter) 70 | } 71 | 72 | public subscript(key: String, nested nested: Bool) -> Map { 73 | return self.subscript(key: key, nested: nested) 74 | } 75 | 76 | public subscript(key: String, nested nested: Bool, delimiter delimiter: String) -> Map { 77 | return self.subscript(key: key, nested: nested, delimiter: delimiter) 78 | } 79 | 80 | public subscript(key: String, ignoreNil ignoreNil: Bool) -> Map { 81 | return self.subscript(key: key, ignoreNil: ignoreNil) 82 | } 83 | 84 | public subscript(key: String, delimiter delimiter: String, ignoreNil ignoreNil: Bool) -> Map { 85 | return self.subscript(key: key, delimiter: delimiter, ignoreNil: ignoreNil) 86 | } 87 | 88 | public subscript(key: String, nested nested: Bool, ignoreNil ignoreNil: Bool) -> Map { 89 | return self.subscript(key: key, nested: nested, ignoreNil: ignoreNil) 90 | } 91 | 92 | public subscript(key: String, nested nested: Bool?, delimiter delimiter: String, ignoreNil ignoreNil: Bool) -> Map { 93 | return self.subscript(key: key, nested: nested, delimiter: delimiter, ignoreNil: ignoreNil) 94 | } 95 | 96 | private func `subscript`(key: String, nested: Bool? = nil, delimiter: String = ".", ignoreNil: Bool = false) -> Map { 97 | // save key and value associated to it 98 | currentKey = key 99 | keyIsNested = nested ?? key.contains(delimiter) 100 | nestedKeyDelimiter = delimiter 101 | 102 | if mappingType == .fromJSON { 103 | // check if a value exists for the current key 104 | // do this pre-check for performance reasons 105 | if keyIsNested { 106 | // break down the components of the key that are separated by delimiter 107 | (isKeyPresent, currentValue) = valueFor(ArraySlice(key.components(separatedBy: delimiter)), dictionary: JSON) 108 | } else { 109 | let object = JSON[key] 110 | let isNSNull = object is NSNull 111 | isKeyPresent = isNSNull ? true : object != nil 112 | currentValue = isNSNull ? nil : object 113 | } 114 | 115 | // update isKeyPresent if ignoreNil is true 116 | if ignoreNil && currentValue == nil { 117 | isKeyPresent = false 118 | } 119 | } 120 | 121 | return self 122 | } 123 | 124 | public func value() -> T? { 125 | let value = currentValue as? T 126 | 127 | // Swift 4.1 breaks Float casting from `NSNumber`. So Added extra checks for `Float` `[Float]` and `[String:Float]` 128 | if value == nil && T.self == Float.self { 129 | if let v = currentValue as? NSNumber { 130 | return v.floatValue as? T 131 | } 132 | } else if value == nil && T.self == [Float].self { 133 | if let v = currentValue as? [Double] { 134 | #if swift(>=4.1) 135 | return v.compactMap{ Float($0) } as? T 136 | #else 137 | return v.flatMap{ Float($0) } as? T 138 | #endif 139 | } 140 | } else if value == nil && T.self == [String:Float].self { 141 | if let v = currentValue as? [String:Double] { 142 | return v.mapValues{ Float($0) } as? T 143 | } 144 | } 145 | return value 146 | } 147 | } 148 | 149 | /// Fetch value from JSON dictionary, loop through keyPathComponents until we reach the desired object 150 | private func valueFor(_ keyPathComponents: ArraySlice, dictionary: [String: Any]) -> (Bool, Any?) { 151 | // Implement it as a tail recursive function. 152 | if keyPathComponents.isEmpty { 153 | return (false, nil) 154 | } 155 | 156 | if let keyPath = keyPathComponents.first { 157 | let isTail = keyPathComponents.count == 1 158 | let object = dictionary[keyPath] 159 | if object is NSNull { 160 | return (isTail, nil) 161 | } else if keyPathComponents.count > 1, let dict = object as? [String: Any] { 162 | let tail = keyPathComponents.dropFirst() 163 | return valueFor(tail, dictionary: dict) 164 | } else if keyPathComponents.count > 1, let array = object as? [Any] { 165 | let tail = keyPathComponents.dropFirst() 166 | return valueFor(tail, array: array) 167 | } else { 168 | return (isTail && object != nil, object) 169 | } 170 | } 171 | 172 | return (false, nil) 173 | } 174 | 175 | /// Fetch value from JSON Array, loop through keyPathComponents them until we reach the desired object 176 | private func valueFor(_ keyPathComponents: ArraySlice, array: [Any]) -> (Bool, Any?) { 177 | // Implement it as a tail recursive function. 178 | 179 | if keyPathComponents.isEmpty { 180 | return (false, nil) 181 | } 182 | 183 | //Try to convert keypath to Int as index 184 | if let keyPath = keyPathComponents.first, 185 | let index = Int(keyPath) , index >= 0 && index < array.count { 186 | 187 | let isTail = keyPathComponents.count == 1 188 | let object = array[index] 189 | 190 | if object is NSNull { 191 | return (isTail, nil) 192 | } else if keyPathComponents.count > 1, let array = object as? [Any] { 193 | let tail = keyPathComponents.dropFirst() 194 | return valueFor(tail, array: array) 195 | } else if keyPathComponents.count > 1, let dict = object as? [String: Any] { 196 | let tail = keyPathComponents.dropFirst() 197 | return valueFor(tail, dictionary: dict) 198 | } else { 199 | return (isTail, object) 200 | } 201 | } 202 | 203 | return (false, nil) 204 | } 205 | 206 | // MARK: - Default Value 207 | 208 | public extension Map { 209 | 210 | /// Returns `default` value if there is nothing to parse. 211 | func value(_ key: String, default: T.Object, using transform: T) throws -> T.Object where T: TransformType { 212 | if let value: T.Object = try? self.value(key, using: transform) { 213 | return value 214 | } else { 215 | return `default` 216 | } 217 | } 218 | 219 | /// Returns `default` value if there is nothing to parse. 220 | func value(_ key: String, default: T) throws -> T { 221 | if let value: T = try? self.value(key) { 222 | return value 223 | } else { 224 | return `default` 225 | } 226 | } 227 | 228 | /// Returns `default` value if there is nothing to parse. 229 | func value(_ key: String, default: [T]) -> [T] { 230 | do { 231 | let value: [T] = try self.value(key) 232 | return value 233 | } catch { 234 | return `default` 235 | } 236 | } 237 | 238 | /// Returns `default` value if there is nothing to parse. 239 | func value(_ key: String, default: T) throws -> T where T: BaseMappable { 240 | if let value: T = try? self.value(key) as T { 241 | return value 242 | } else { 243 | return `default` 244 | } 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /Sources/MapError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MapError.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2016-09-26. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | 31 | public struct MapError: Error { 32 | public var key: String? 33 | public var currentValue: Any? 34 | public var reason: String? 35 | public var file: StaticString? 36 | public var function: StaticString? 37 | public var line: UInt? 38 | 39 | public init(key: String?, currentValue: Any?, reason: String?, file: StaticString? = nil, function: StaticString? = nil, line: UInt? = nil) { 40 | self.key = key 41 | self.currentValue = currentValue 42 | self.reason = reason 43 | self.file = file 44 | self.function = function 45 | self.line = line 46 | } 47 | } 48 | 49 | extension MapError: CustomStringConvertible { 50 | 51 | private var location: String? { 52 | guard let file = file, let function = function, let line = line else { return nil } 53 | let fileName = ((String(describing: file).components(separatedBy: "/").last ?? "").components(separatedBy: ".").first ?? "") 54 | return "\(fileName).\(function):\(line)" 55 | } 56 | 57 | public var description: String { 58 | let info: [(String, Any?)] = [ 59 | ("- reason", reason), 60 | ("- location", location), 61 | ("- key", key), 62 | ("- currentValue", currentValue), 63 | ] 64 | let infoString = info.map { "\($0.0): \($0.1 ?? "nil")" }.joined(separator: "\n") 65 | return "Got an error while mapping.\n\(infoString)" 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /Sources/Mappable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Mappable.swift 3 | // ObjectMapper 4 | // 5 | // Created by Scott Hoyt on 10/25/15. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | 31 | /// BaseMappable should not be implemented directly. Mappable or StaticMappable should be used instead 32 | public protocol BaseMappable { 33 | /// This function is where all variable mappings should occur. It is executed by Mapper during the mapping (serialization and deserialization) process. 34 | mutating func mapping(map: Map) 35 | } 36 | 37 | public protocol Mappable: BaseMappable { 38 | /// This function can be used to validate JSON prior to mapping. Return nil to cancel mapping at this point 39 | init?(map: Map) 40 | } 41 | 42 | public protocol StaticMappable: BaseMappable { 43 | /// This is function that can be used to: 44 | /// 1) provide an existing cached object to be used for mapping 45 | /// 2) return an object of another class (which conforms to BaseMappable) to be used for mapping. For instance, you may inspect the JSON to infer the type of object that should be used for any given mapping 46 | static func objectForMapping(map: Map) -> BaseMappable? 47 | } 48 | 49 | public extension Mappable { 50 | 51 | /// Initializes object from a JSON String 52 | init?(JSONString: String, context: MapContext? = nil) { 53 | if let obj: Self = Mapper(context: context).map(JSONString: JSONString) { 54 | self = obj 55 | } else { 56 | return nil 57 | } 58 | } 59 | 60 | /// Initializes object from a JSON Dictionary 61 | init?(JSON: [String: Any], context: MapContext? = nil) { 62 | if let obj: Self = Mapper(context: context).map(JSON: JSON) { 63 | self = obj 64 | } else { 65 | return nil 66 | } 67 | } 68 | } 69 | 70 | public extension BaseMappable { 71 | 72 | /// Returns the JSON Dictionary for the object 73 | func toJSON() -> [String: Any] { 74 | return Mapper().toJSON(self) 75 | } 76 | 77 | /// Returns the JSON String for the object 78 | func toJSONString(prettyPrint: Bool = false) -> String? { 79 | return Mapper().toJSONString(self, prettyPrint: prettyPrint) 80 | } 81 | } 82 | 83 | public extension Array where Element: BaseMappable { 84 | 85 | /// Initialize Array from a JSON String 86 | init?(JSONString: String, context: MapContext? = nil) { 87 | if let obj: [Element] = Mapper(context: context).mapArray(JSONString: JSONString) { 88 | self = obj 89 | } else { 90 | return nil 91 | } 92 | } 93 | 94 | /// Initialize Array from a JSON Array 95 | init(JSONArray: [[String: Any]], context: MapContext? = nil) { 96 | let obj: [Element] = Mapper(context: context).mapArray(JSONArray: JSONArray) 97 | self = obj 98 | } 99 | 100 | /// Returns the JSON Array 101 | func toJSON() -> [[String: Any]] { 102 | return Mapper().toJSONArray(self) 103 | } 104 | 105 | /// Returns the JSON String for the object 106 | func toJSONString(prettyPrint: Bool = false) -> String? { 107 | return Mapper().toJSONString(self, prettyPrint: prettyPrint) 108 | } 109 | } 110 | 111 | public extension Set where Element: BaseMappable { 112 | 113 | /// Initializes a set from a JSON String 114 | init?(JSONString: String, context: MapContext? = nil) { 115 | if let obj: Set = Mapper(context: context).mapSet(JSONString: JSONString) { 116 | self = obj 117 | } else { 118 | return nil 119 | } 120 | } 121 | 122 | /// Initializes a set from JSON 123 | init?(JSONArray: [[String: Any]], context: MapContext? = nil) { 124 | guard let obj = Mapper(context: context).mapSet(JSONArray: JSONArray) as Set? else { 125 | return nil 126 | } 127 | self = obj 128 | } 129 | 130 | /// Returns the JSON Set 131 | func toJSON() -> [[String: Any]] { 132 | return Mapper().toJSONSet(self) 133 | } 134 | 135 | /// Returns the JSON String for the object 136 | func toJSONString(prettyPrint: Bool = false) -> String? { 137 | return Mapper().toJSONString(self, prettyPrint: prettyPrint) 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /Sources/NSDecimalNumberTransform.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TransformOf.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 8/22/16. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | 31 | open class NSDecimalNumberTransform: TransformType { 32 | public typealias Object = NSDecimalNumber 33 | public typealias JSON = String 34 | 35 | public init() {} 36 | 37 | open func transformFromJSON(_ value: Any?) -> NSDecimalNumber? { 38 | if let string = value as? String { 39 | return NSDecimalNumber(string: string) 40 | } else if let number = value as? NSNumber { 41 | return NSDecimalNumber(decimal: number.decimalValue) 42 | } else if let double = value as? Double { 43 | return NSDecimalNumber(floatLiteral: double) 44 | } 45 | return nil 46 | } 47 | 48 | open func transformToJSON(_ value: NSDecimalNumber?) -> String? { 49 | guard let value = value else { return nil } 50 | return value.description 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Sources/ObjectMapper.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjectMapper.h 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2014-10-16. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | 30 | #import 31 | 32 | //! Project version number for ObjectMapper. 33 | FOUNDATION_EXPORT double ObjectMapperVersionNumber; 34 | 35 | //! Project version string for ObjectMapper. 36 | FOUNDATION_EXPORT const unsigned char ObjectMapperVersionString[]; 37 | 38 | // In this header, you should import all the public headers of your framework using statements like #import 39 | 40 | 41 | -------------------------------------------------------------------------------- /Sources/Operators.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Operators.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2014-10-09. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | /** 30 | * This file defines a new operator which is used to create a mapping between an object and a JSON key value. 31 | * There is an overloaded operator definition for each type of object that is supported in ObjectMapper. 32 | * This provides a way to add custom logic to handle specific types of objects 33 | */ 34 | 35 | /// Operator used for defining mappings to and from JSON 36 | infix operator <- 37 | 38 | /// Operator used to define mappings to JSON 39 | infix operator >>> 40 | 41 | // MARK:- Objects with Basic types 42 | 43 | /// Object of Basic type 44 | public func <- (left: inout T, right: Map) { 45 | switch right.mappingType { 46 | case .fromJSON where right.isKeyPresent: 47 | FromJSON.basicType(&left, object: right.value()) 48 | case .toJSON: 49 | left >>> right 50 | default: () 51 | } 52 | } 53 | 54 | public func >>> (left: T, right: Map) { 55 | if right.mappingType == .toJSON { 56 | ToJSON.basicType(left, map: right) 57 | } 58 | } 59 | 60 | 61 | /// Optional object of basic type 62 | public func <- (left: inout T?, right: Map) { 63 | switch right.mappingType { 64 | case .fromJSON where right.isKeyPresent: 65 | FromJSON.optionalBasicType(&left, object: right.value()) 66 | case .toJSON: 67 | left >>> right 68 | default: () 69 | } 70 | } 71 | 72 | public func >>> (left: T?, right: Map) { 73 | if right.mappingType == .toJSON { 74 | ToJSON.optionalBasicType(left, map: right) 75 | } 76 | } 77 | 78 | 79 | // Code targeting the Swift 4.1 compiler and below. 80 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 81 | /// Implicitly unwrapped optional object of basic type 82 | public func <- (left: inout T!, right: Map) { 83 | switch right.mappingType { 84 | case .fromJSON where right.isKeyPresent: 85 | FromJSON.optionalBasicType(&left, object: right.value()) 86 | case .toJSON: 87 | left >>> right 88 | default: () 89 | } 90 | } 91 | #endif 92 | 93 | // MARK:- Mappable Objects - 94 | 95 | /// Object conforming to Mappable 96 | public func <- (left: inout T, right: Map) { 97 | switch right.mappingType { 98 | case .fromJSON: 99 | FromJSON.object(&left, map: right) 100 | case .toJSON: 101 | left >>> right 102 | } 103 | } 104 | 105 | public func >>> (left: T, right: Map) { 106 | if right.mappingType == .toJSON { 107 | ToJSON.object(left, map: right) 108 | } 109 | } 110 | 111 | 112 | /// Optional Mappable objects 113 | public func <- (left: inout T?, right: Map) { 114 | switch right.mappingType { 115 | case .fromJSON where right.isKeyPresent: 116 | FromJSON.optionalObject(&left, map: right) 117 | case .toJSON: 118 | left >>> right 119 | default: () 120 | } 121 | } 122 | 123 | public func >>> (left: T?, right: Map) { 124 | if right.mappingType == .toJSON { 125 | ToJSON.optionalObject(left, map: right) 126 | } 127 | } 128 | 129 | 130 | // Code targeting the Swift 4.1 compiler and below. 131 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 132 | /// Implicitly unwrapped optional Mappable objects 133 | public func <- (left: inout T!, right: Map) { 134 | switch right.mappingType { 135 | case .fromJSON where right.isKeyPresent: 136 | FromJSON.optionalObject(&left, map: right) 137 | case .toJSON: 138 | left >>> right 139 | default: () 140 | } 141 | } 142 | #endif 143 | 144 | // MARK:- Dictionary of Mappable objects - Dictionary 145 | 146 | /// Dictionary of Mappable objects 147 | public func <- (left: inout Dictionary, right: Map) { 148 | switch right.mappingType { 149 | case .fromJSON where right.isKeyPresent: 150 | FromJSON.objectDictionary(&left, map: right) 151 | case .toJSON: 152 | left >>> right 153 | default: () 154 | } 155 | } 156 | 157 | public func >>> (left: Dictionary, right: Map) { 158 | if right.mappingType == .toJSON { 159 | ToJSON.objectDictionary(left, map: right) 160 | } 161 | } 162 | 163 | 164 | /// Optional Dictionary of Mappable object 165 | public func <- (left: inout Dictionary?, right: Map) { 166 | switch right.mappingType { 167 | case .fromJSON where right.isKeyPresent: 168 | FromJSON.optionalObjectDictionary(&left, map: right) 169 | case .toJSON: 170 | left >>> right 171 | default: () 172 | } 173 | } 174 | 175 | public func >>> (left: Dictionary?, right: Map) { 176 | if right.mappingType == .toJSON { 177 | ToJSON.optionalObjectDictionary(left, map: right) 178 | } 179 | } 180 | 181 | 182 | // Code targeting the Swift 4.1 compiler and below. 183 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 184 | /// Implicitly unwrapped Optional Dictionary of Mappable object 185 | public func <- (left: inout Dictionary!, right: Map) { 186 | switch right.mappingType { 187 | case .fromJSON where right.isKeyPresent: 188 | FromJSON.optionalObjectDictionary(&left, map: right) 189 | case .toJSON: 190 | left >>> right 191 | default: () 192 | } 193 | } 194 | #endif 195 | 196 | /// Dictionary of Mappable objects 197 | public func <- (left: inout Dictionary, right: Map) { 198 | switch right.mappingType { 199 | case .fromJSON where right.isKeyPresent: 200 | FromJSON.objectDictionaryOfArrays(&left, map: right) 201 | case .toJSON: 202 | left >>> right 203 | default: () 204 | } 205 | } 206 | 207 | public func >>> (left: Dictionary, right: Map) { 208 | if right.mappingType == .toJSON { 209 | ToJSON.objectDictionaryOfArrays(left, map: right) 210 | } 211 | } 212 | 213 | /// Optional Dictionary of Mappable object 214 | public func <- (left: inout Dictionary?, right: Map) { 215 | switch right.mappingType { 216 | case .fromJSON where right.isKeyPresent: 217 | FromJSON.optionalObjectDictionaryOfArrays(&left, map: right) 218 | case .toJSON: 219 | left >>> right 220 | default: () 221 | } 222 | } 223 | 224 | public func >>> (left: Dictionary?, right: Map) { 225 | if right.mappingType == .toJSON { 226 | ToJSON.optionalObjectDictionaryOfArrays(left, map: right) 227 | } 228 | } 229 | 230 | 231 | // Code targeting the Swift 4.1 compiler and below. 232 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 233 | /// Implicitly unwrapped Optional Dictionary of Mappable object 234 | public func <- (left: inout Dictionary!, right: Map) { 235 | switch right.mappingType { 236 | case .fromJSON where right.isKeyPresent: 237 | FromJSON.optionalObjectDictionaryOfArrays(&left, map: right) 238 | case .toJSON: 239 | left >>> right 240 | default: () 241 | } 242 | } 243 | #endif 244 | 245 | // MARK:- Array of Mappable objects - Array 246 | 247 | /// Array of Mappable objects 248 | public func <- (left: inout Array, right: Map) { 249 | switch right.mappingType { 250 | case .fromJSON where right.isKeyPresent: 251 | FromJSON.objectArray(&left, map: right) 252 | case .toJSON: 253 | left >>> right 254 | default: () 255 | } 256 | } 257 | 258 | public func >>> (left: Array, right: Map) { 259 | if right.mappingType == .toJSON { 260 | ToJSON.objectArray(left, map: right) 261 | } 262 | } 263 | 264 | /// Optional array of Mappable objects 265 | public func <- (left: inout Array?, right: Map) { 266 | switch right.mappingType { 267 | case .fromJSON where right.isKeyPresent: 268 | FromJSON.optionalObjectArray(&left, map: right) 269 | case .toJSON: 270 | left >>> right 271 | default: () 272 | } 273 | } 274 | 275 | public func >>> (left: Array?, right: Map) { 276 | if right.mappingType == .toJSON { 277 | ToJSON.optionalObjectArray(left, map: right) 278 | } 279 | } 280 | 281 | 282 | // Code targeting the Swift 4.1 compiler and below. 283 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 284 | /// Implicitly unwrapped Optional array of Mappable objects 285 | public func <- (left: inout Array!, right: Map) { 286 | switch right.mappingType { 287 | case .fromJSON where right.isKeyPresent: 288 | FromJSON.optionalObjectArray(&left, map: right) 289 | case .toJSON: 290 | left >>> right 291 | default: () 292 | } 293 | } 294 | #endif 295 | 296 | // MARK:- Array of Array of Mappable objects - Array> 297 | 298 | /// Array of Array Mappable objects 299 | public func <- (left: inout Array>, right: Map) { 300 | switch right.mappingType { 301 | case .fromJSON where right.isKeyPresent: 302 | FromJSON.twoDimensionalObjectArray(&left, map: right) 303 | case .toJSON: 304 | left >>> right 305 | default: () 306 | } 307 | } 308 | 309 | public func >>> (left: Array>, right: Map) { 310 | if right.mappingType == .toJSON { 311 | ToJSON.twoDimensionalObjectArray(left, map: right) 312 | } 313 | } 314 | 315 | 316 | /// Optional array of Mappable objects 317 | public func <- (left:inout Array>?, right: Map) { 318 | switch right.mappingType { 319 | case .fromJSON where right.isKeyPresent: 320 | FromJSON.optionalTwoDimensionalObjectArray(&left, map: right) 321 | case .toJSON: 322 | left >>> right 323 | default: () 324 | } 325 | } 326 | 327 | public func >>> (left: Array>?, right: Map) { 328 | if right.mappingType == .toJSON { 329 | ToJSON.optionalTwoDimensionalObjectArray(left, map: right) 330 | } 331 | } 332 | 333 | 334 | // Code targeting the Swift 4.1 compiler and below. 335 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 336 | /// Implicitly unwrapped Optional array of Mappable objects 337 | public func <- (left: inout Array>!, right: Map) { 338 | switch right.mappingType { 339 | case .fromJSON where right.isKeyPresent: 340 | FromJSON.optionalTwoDimensionalObjectArray(&left, map: right) 341 | case .toJSON: 342 | left >>> right 343 | default: () 344 | } 345 | } 346 | #endif 347 | 348 | // MARK:- Set of Mappable objects - Set 349 | 350 | /// Set of Mappable objects 351 | public func <- (left: inout Set, right: Map) { 352 | switch right.mappingType { 353 | case .fromJSON where right.isKeyPresent: 354 | FromJSON.objectSet(&left, map: right) 355 | case .toJSON: 356 | left >>> right 357 | default: () 358 | } 359 | } 360 | 361 | public func >>> (left: Set, right: Map) { 362 | if right.mappingType == .toJSON { 363 | ToJSON.objectSet(left, map: right) 364 | } 365 | } 366 | 367 | 368 | /// Optional Set of Mappable objects 369 | public func <- (left: inout Set?, right: Map) { 370 | switch right.mappingType { 371 | case .fromJSON where right.isKeyPresent: 372 | FromJSON.optionalObjectSet(&left, map: right) 373 | case .toJSON: 374 | left >>> right 375 | default: () 376 | } 377 | } 378 | 379 | public func >>> (left: Set?, right: Map) { 380 | if right.mappingType == .toJSON { 381 | ToJSON.optionalObjectSet(left, map: right) 382 | } 383 | } 384 | 385 | 386 | // Code targeting the Swift 4.1 compiler and below. 387 | #if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) 388 | /// Implicitly unwrapped Optional Set of Mappable objects 389 | public func <- (left: inout Set!, right: Map) { 390 | switch right.mappingType { 391 | case .fromJSON where right.isKeyPresent: 392 | FromJSON.optionalObjectSet(&left, map: right) 393 | case .toJSON: 394 | left >>> right 395 | default: () 396 | } 397 | } 398 | #endif 399 | -------------------------------------------------------------------------------- /Sources/Resources/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | NSPrivacyCollectedDataTypes 8 | 9 | NSPrivacyTracking 10 | 11 | NSPrivacyTrackingDomains 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Sources/ToJSON.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ToJSON.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2014-10-13. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | 31 | private func setValue(_ value: Any, map: Map) { 32 | setValue(value, key: map.currentKey!, checkForNestedKeys: map.keyIsNested, delimiter: map.nestedKeyDelimiter, dictionary: &map.JSON) 33 | } 34 | 35 | private func setValue(_ value: Any, key: String, checkForNestedKeys: Bool, delimiter: String, dictionary: inout [String : Any]) { 36 | if checkForNestedKeys { 37 | let keyComponents = ArraySlice(key.components(separatedBy: delimiter).filter { !$0.isEmpty }.map { $0 }) 38 | setValue(value, forKeyPathComponents: keyComponents, dictionary: &dictionary) 39 | } else { 40 | dictionary[key] = value 41 | } 42 | } 43 | 44 | private func setValue(_ value: Any, forKeyPathComponents components: ArraySlice, dictionary: inout [String : Any]) { 45 | guard let head = components.first else { 46 | return 47 | } 48 | 49 | let headAsString = String(head) 50 | if components.count == 1 { 51 | dictionary[headAsString] = value 52 | } else { 53 | var child = dictionary[headAsString] as? [String : Any] ?? [:] 54 | 55 | let tail = components.dropFirst() 56 | setValue(value, forKeyPathComponents: tail, dictionary: &child) 57 | 58 | dictionary[headAsString] = child 59 | } 60 | } 61 | 62 | internal final class ToJSON { 63 | 64 | class func basicType(_ field: N, map: Map) { 65 | if let x = field as Any? , false 66 | || x is NSNumber // Basic types 67 | || x is Bool 68 | || x is Int 69 | || x is Double 70 | || x is Float 71 | || x is String 72 | || x is NSNull 73 | || x is Array // Arrays 74 | || x is Array 75 | || x is Array 76 | || x is Array 77 | || x is Array 78 | || x is Array 79 | || x is Array 80 | || x is Array> 81 | || x is Dictionary // Dictionaries 82 | || x is Dictionary 83 | || x is Dictionary 84 | || x is Dictionary 85 | || x is Dictionary 86 | || x is Dictionary 87 | || x is Dictionary 88 | { 89 | setValue(x, map: map) 90 | } 91 | } 92 | 93 | class func optionalBasicType(_ field: N?, map: Map) { 94 | if let field = field { 95 | basicType(field, map: map) 96 | } else if map.shouldIncludeNilValues { 97 | basicType(NSNull(), map: map) //If BasicType is nil, emit NSNull into the JSON output 98 | } 99 | } 100 | 101 | class func object(_ field: N, map: Map) { 102 | if let result = Mapper(context: map.context, shouldIncludeNilValues: map.shouldIncludeNilValues).toJSON(field) as Any? { 103 | setValue(result, map: map) 104 | } 105 | } 106 | 107 | class func optionalObject(_ field: N?, map: Map) { 108 | if let field = field { 109 | object(field, map: map) 110 | } else if map.shouldIncludeNilValues { 111 | basicType(NSNull(), map: map) //If field is nil, emit NSNull into the JSON output 112 | } 113 | } 114 | 115 | class func objectArray(_ field: Array, map: Map) { 116 | let JSONObjects = Mapper(context: map.context, shouldIncludeNilValues: map.shouldIncludeNilValues).toJSONArray(field) 117 | 118 | setValue(JSONObjects, map: map) 119 | } 120 | 121 | class func optionalObjectArray(_ field: Array?, map: Map) { 122 | if let field = field { 123 | objectArray(field, map: map) 124 | } 125 | } 126 | 127 | class func twoDimensionalObjectArray(_ field: Array>, map: Map) { 128 | var array = [[[String: Any]]]() 129 | for innerArray in field { 130 | let JSONObjects = Mapper(context: map.context, shouldIncludeNilValues: map.shouldIncludeNilValues).toJSONArray(innerArray) 131 | array.append(JSONObjects) 132 | } 133 | setValue(array, map: map) 134 | } 135 | 136 | class func optionalTwoDimensionalObjectArray(_ field: Array>?, map: Map) { 137 | if let field = field { 138 | twoDimensionalObjectArray(field, map: map) 139 | } 140 | } 141 | 142 | class func objectSet(_ field: Set, map: Map) { 143 | let JSONObjects = Mapper(context: map.context, shouldIncludeNilValues: map.shouldIncludeNilValues).toJSONSet(field) 144 | 145 | setValue(JSONObjects, map: map) 146 | } 147 | 148 | class func optionalObjectSet(_ field: Set?, map: Map) { 149 | if let field = field { 150 | objectSet(field, map: map) 151 | } 152 | } 153 | 154 | class func objectDictionary(_ field: Dictionary, map: Map) { 155 | let JSONObjects = Mapper(context: map.context, shouldIncludeNilValues: map.shouldIncludeNilValues).toJSONDictionary(field) 156 | 157 | setValue(JSONObjects, map: map) 158 | } 159 | 160 | class func optionalObjectDictionary(_ field: Dictionary?, map: Map) { 161 | if let field = field { 162 | objectDictionary(field, map: map) 163 | } 164 | } 165 | 166 | class func objectDictionaryOfArrays(_ field: Dictionary, map: Map) { 167 | let JSONObjects = Mapper(context: map.context, shouldIncludeNilValues: map.shouldIncludeNilValues).toJSONDictionaryOfArrays(field) 168 | 169 | setValue(JSONObjects, map: map) 170 | } 171 | 172 | class func optionalObjectDictionaryOfArrays(_ field: Dictionary?, map: Map) { 173 | if let field = field { 174 | objectDictionaryOfArrays(field, map: map) 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /Sources/TransformOf.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TransformOf.swift 3 | // ObjectMapper 4 | // 5 | // Created by Syo Ikeda on 1/23/15. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | open class TransformOf: TransformType { 30 | public typealias Object = ObjectType 31 | public typealias JSON = JSONType 32 | 33 | private let fromJSON: (JSONType?) -> ObjectType? 34 | private let toJSON: (ObjectType?) -> JSONType? 35 | 36 | public init(fromJSON: @escaping(JSONType?) -> ObjectType?, toJSON: @escaping(ObjectType?) -> JSONType?) { 37 | self.fromJSON = fromJSON 38 | self.toJSON = toJSON 39 | } 40 | 41 | open func transformFromJSON(_ value: Any?) -> ObjectType? { 42 | return fromJSON(value as? JSONType) 43 | } 44 | 45 | open func transformToJSON(_ value: ObjectType?) -> JSONType? { 46 | return toJSON(value) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Sources/TransformType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TransformType.swift 3 | // ObjectMapper 4 | // 5 | // Created by Syo Ikeda on 2/4/15. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | public protocol TransformType { 30 | associatedtype Object 31 | associatedtype JSON 32 | 33 | func transformFromJSON(_ value: Any?) -> Object? 34 | func transformToJSON(_ value: Object?) -> JSON? 35 | } 36 | -------------------------------------------------------------------------------- /Sources/URLTransform.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLTransform.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2014-10-27. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | 31 | open class URLTransform: TransformType { 32 | public typealias Object = URL 33 | public typealias JSON = String 34 | private let shouldEncodeURLString: Bool 35 | private let allowedCharacterSet: CharacterSet 36 | 37 | /** 38 | Initializes the URLTransform with an option to encode URL strings before converting them to an NSURL 39 | - parameter shouldEncodeUrlString: when true (the default) the string is encoded before passing 40 | to `NSURL(string:)` 41 | - returns: an initialized transformer 42 | */ 43 | public init(shouldEncodeURLString: Bool = false, allowedCharacterSet: CharacterSet = .urlQueryAllowed) { 44 | self.shouldEncodeURLString = shouldEncodeURLString 45 | self.allowedCharacterSet = allowedCharacterSet 46 | } 47 | 48 | open func transformFromJSON(_ value: Any?) -> URL? { 49 | guard let URLString = value as? String else { return nil } 50 | 51 | if !shouldEncodeURLString { 52 | return URL(string: URLString) 53 | } 54 | 55 | guard let escapedURLString = URLString.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) else { 56 | return nil 57 | } 58 | return URL(string: escapedURLString) 59 | } 60 | 61 | open func transformToJSON(_ value: URL?) -> String? { 62 | if let URL = value { 63 | return URL.absoluteString 64 | } 65 | return nil 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Tests/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 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/BasicTypes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BasicTypes.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2015-02-17. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | import ObjectMapper 31 | 32 | class BasicTypes: Mappable { 33 | var bool: Bool = true 34 | var boolOptional: Bool? 35 | var boolImplicityUnwrapped: Bool! 36 | 37 | var int: Int = 0 38 | var intOptional: Int? 39 | var intImplicityUnwrapped: Int! 40 | 41 | var int8: Int8 = 0 42 | var int8Optional: Int8? 43 | var int8ImplicityUnwrapped: Int8! 44 | 45 | var int16: Int16 = 0 46 | var int16Optional: Int16? 47 | var int16ImplicityUnwrapped: Int16! 48 | 49 | var int32: Int32 = 0 50 | var int32Optional: Int32? 51 | var int32ImplicityUnwrapped: Int32! 52 | 53 | var int64: Int64 = 0 54 | var int64Optional: Int64? 55 | var int64ImplicityUnwrapped: Int64! 56 | 57 | var uint: UInt = 0 58 | var uintOptional: UInt? 59 | var uintImplicityUnwrapped: UInt! 60 | 61 | var uint8: UInt8 = 0 62 | var uint8Optional: UInt8? 63 | var uint8ImplicityUnwrapped: UInt8! 64 | 65 | var uint16: UInt16 = 0 66 | var uint16Optional: UInt16? 67 | var uint16ImplicityUnwrapped: UInt16! 68 | 69 | var uint32: UInt32 = 0 70 | var uint32Optional: UInt32? 71 | var uint32ImplicityUnwrapped: UInt32! 72 | 73 | var uint64: UInt64 = 0 74 | var uint64Optional: UInt64? 75 | var uint64ImplicityUnwrapped: UInt64! 76 | 77 | var double: Double = 1.1 78 | var doubleOptional: Double? 79 | var doubleImplicityUnwrapped: Double! 80 | var float: Float = 1.11 81 | var floatOptional: Float? 82 | var floatImplicityUnwrapped: Float! 83 | var string: String = "" 84 | var stringOptional: String? 85 | var stringImplicityUnwrapped: String! 86 | var anyObject: Any = true 87 | var anyObjectOptional: Any? 88 | var anyObjectImplicitlyUnwrapped: Any! 89 | 90 | var arrayBool: Array = [] 91 | var arrayBoolOptional: Array? 92 | var arrayBoolImplicityUnwrapped: Array! 93 | var arrayInt: Array = [] 94 | var arrayIntOptional: Array? 95 | var arrayIntImplicityUnwrapped: Array! 96 | var arrayDouble: Array = [] 97 | var arrayDoubleOptional: Array? 98 | var arrayDoubleImplicityUnwrapped: Array! 99 | var arrayFloat: Array = [] 100 | var arrayFloatOptional: Array? 101 | var arrayFloatImplicityUnwrapped: Array! 102 | var arrayString: Array = [] 103 | var arrayStringOptional: Array? 104 | var arrayStringImplicityUnwrapped: Array! 105 | var arrayAnyObject: Array = [] 106 | var arrayAnyObjectOptional: Array? 107 | var arrayAnyObjectImplicitlyUnwrapped: Array! 108 | 109 | var dictBool: Dictionary = [:] 110 | var dictBoolOptional: Dictionary? 111 | var dictBoolImplicityUnwrapped: Dictionary! 112 | var dictInt: Dictionary = [:] 113 | var dictIntOptional: Dictionary? 114 | var dictIntImplicityUnwrapped: Dictionary! 115 | var dictDouble: Dictionary = [:] 116 | var dictDoubleOptional: Dictionary? 117 | var dictDoubleImplicityUnwrapped: Dictionary! 118 | var dictFloat: Dictionary = [:] 119 | var dictFloatOptional: Dictionary? 120 | var dictFloatImplicityUnwrapped: Dictionary! 121 | var dictString: Dictionary = [:] 122 | var dictStringOptional: Dictionary? 123 | var dictStringImplicityUnwrapped: Dictionary! 124 | var dictAnyObject: Dictionary = [:] 125 | var dictAnyObjectOptional: Dictionary? 126 | var dictAnyObjectImplicitlyUnwrapped: Dictionary! 127 | 128 | enum EnumInt: Int { 129 | case Default 130 | case Another 131 | } 132 | var enumInt: EnumInt = .Default 133 | var enumIntOptional: EnumInt? 134 | var enumIntImplicitlyUnwrapped: EnumInt! 135 | 136 | enum EnumDouble: Double { 137 | case Default 138 | case Another 139 | } 140 | var enumDouble: EnumDouble = .Default 141 | var enumDoubleOptional: EnumDouble? 142 | var enumDoubleImplicitlyUnwrapped: EnumDouble! 143 | 144 | enum EnumFloat: Float { 145 | case Default 146 | case Another 147 | } 148 | var enumFloat: EnumFloat = .Default 149 | var enumFloatOptional: EnumFloat? 150 | var enumFloatImplicitlyUnwrapped: EnumFloat! 151 | 152 | enum EnumString: String { 153 | case Default = "Default" 154 | case Another = "Another" 155 | } 156 | var enumString: EnumString = .Default 157 | var enumStringOptional: EnumString? 158 | var enumStringImplicitlyUnwrapped: EnumString! 159 | 160 | var arrayEnumInt: [EnumInt] = [] 161 | var arrayEnumIntOptional: [EnumInt]? 162 | var arrayEnumIntImplicitlyUnwrapped: [EnumInt]! 163 | 164 | var dictEnumInt: [String: EnumInt] = [:] 165 | var dictEnumIntOptional: [String: EnumInt]? 166 | var dictEnumIntImplicitlyUnwrapped: [String: EnumInt]! 167 | 168 | init(){ 169 | 170 | } 171 | 172 | required init?(map: Map){ 173 | 174 | } 175 | 176 | func mapping(map: Map) { 177 | bool <- map["bool"] 178 | boolOptional <- map["boolOpt"] 179 | boolImplicityUnwrapped <- map["boolImp"] 180 | 181 | int <- map["int"] 182 | intOptional <- map["intOpt"] 183 | intImplicityUnwrapped <- map["intImp"] 184 | 185 | int8 <- map["int8"] 186 | int8Optional <- map["int8Opt"] 187 | int8ImplicityUnwrapped <- map["int8Imp"] 188 | 189 | int16 <- map["int16"] 190 | int16Optional <- map["int16Opt"] 191 | int16ImplicityUnwrapped <- map["int16Imp"] 192 | 193 | int32 <- map["int32"] 194 | int32Optional <- map["int32Opt"] 195 | int32ImplicityUnwrapped <- map["int32Imp"] 196 | 197 | int64 <- map["int64"] 198 | int64Optional <- map["int64Opt"] 199 | int64ImplicityUnwrapped <- map["int64Imp"] 200 | 201 | uint <- map["uint"] 202 | uintOptional <- map["uintOpt"] 203 | uintImplicityUnwrapped <- map["uintImp"] 204 | 205 | uint8 <- map["uint8"] 206 | uint8Optional <- map["uint8Opt"] 207 | uint8ImplicityUnwrapped <- map["uint8Imp"] 208 | 209 | uint16 <- map["uint16"] 210 | uint16Optional <- map["uint16Opt"] 211 | uint16ImplicityUnwrapped <- map["uint16Imp"] 212 | 213 | uint32 <- map["uint32"] 214 | uint32Optional <- map["uint32Opt"] 215 | uint32ImplicityUnwrapped <- map["uint32Imp"] 216 | 217 | uint64 <- map["uint64"] 218 | uint64Optional <- map["uint64Opt"] 219 | uint64ImplicityUnwrapped <- map["uint64Imp"] 220 | 221 | double <- map["double"] 222 | doubleOptional <- map["doubleOpt"] 223 | doubleImplicityUnwrapped <- map["doubleImp"] 224 | float <- map["float"] 225 | floatOptional <- map["floatOpt"] 226 | floatImplicityUnwrapped <- map["floatImp"] 227 | string <- map["string"] 228 | stringOptional <- map["stringOpt"] 229 | stringImplicityUnwrapped <- map["stringImp"] 230 | anyObject <- map["anyObject"] 231 | anyObjectOptional <- map["anyObjectOpt"] 232 | anyObjectImplicitlyUnwrapped <- map["anyObjectImp"] 233 | 234 | arrayBool <- map["arrayBool"] 235 | arrayBoolOptional <- map["arrayBoolOpt"] 236 | arrayBoolImplicityUnwrapped <- map["arrayBoolImp"] 237 | arrayInt <- map["arrayInt"] 238 | arrayIntOptional <- map["arrayIntOpt"] 239 | arrayIntImplicityUnwrapped <- map["arrayIntImp"] 240 | arrayDouble <- map["arrayDouble"] 241 | arrayDoubleOptional <- map["arrayDoubleOpt"] 242 | arrayDoubleImplicityUnwrapped <- map["arrayDoubleImp"] 243 | arrayFloat <- map["arrayFloat"] 244 | arrayFloatOptional <- map["arrayFloatOpt"] 245 | arrayFloatImplicityUnwrapped <- map["arrayFloatImp"] 246 | arrayString <- map["arrayString"] 247 | arrayStringOptional <- map["arrayStringOpt"] 248 | arrayStringImplicityUnwrapped <- map["arrayStringImp"] 249 | arrayAnyObject <- map["arrayAnyObject"] 250 | arrayAnyObjectOptional <- map["arrayAnyObjectOpt"] 251 | arrayAnyObjectImplicitlyUnwrapped <- map["arrayAnyObjectImp"] 252 | 253 | dictBool <- map["dictBool"] 254 | dictBoolOptional <- map["dictBoolOpt"] 255 | dictBoolImplicityUnwrapped <- map["dictBoolImp"] 256 | dictInt <- map["dictInt"] 257 | dictIntOptional <- map["dictIntOpt"] 258 | dictIntImplicityUnwrapped <- map["dictIntImp"] 259 | dictDouble <- map["dictDouble"] 260 | dictDoubleOptional <- map["dictDoubleOpt"] 261 | dictDoubleImplicityUnwrapped <- map["dictDoubleImp"] 262 | dictFloat <- map["dictFloat"] 263 | dictFloatOptional <- map["dictFloatOpt"] 264 | dictFloatImplicityUnwrapped <- map["dictFloatImp"] 265 | dictString <- map["dictString"] 266 | dictStringOptional <- map["dictStringOpt"] 267 | dictStringImplicityUnwrapped <- map["dictStringImp"] 268 | dictAnyObject <- map["dictAnyObject"] 269 | dictAnyObjectOptional <- map["dictAnyObjectOpt"] 270 | dictAnyObjectImplicitlyUnwrapped <- map["dictAnyObjectImp"] 271 | 272 | enumInt <- map["enumInt"] 273 | enumIntOptional <- map["enumIntOpt"] 274 | enumIntImplicitlyUnwrapped <- map["enumIntImp"] 275 | enumDouble <- map["enumDouble"] 276 | enumDoubleOptional <- map["enumDoubleOpt"] 277 | enumDoubleImplicitlyUnwrapped <- map["enumDoubleImp"] 278 | enumFloat <- map["enumFloat"] 279 | enumFloatOptional <- map["enumFloatOpt"] 280 | enumFloatImplicitlyUnwrapped <- map["enumFloatImp"] 281 | enumString <- map["enumString"] 282 | enumStringOptional <- map["enumStringOpt"] 283 | enumStringImplicitlyUnwrapped <- map["enumStringImp"] 284 | 285 | arrayEnumInt <- map["arrayEnumInt"] 286 | arrayEnumIntOptional <- map["arrayEnumIntOpt"] 287 | arrayEnumIntImplicitlyUnwrapped <- map["arrayEnumIntImp"] 288 | 289 | dictEnumInt <- map["dictEnumInt"] 290 | dictEnumIntOptional <- map["dictEnumIntOpt"] 291 | dictEnumIntImplicitlyUnwrapped <- map["dictEnumIntImp"] 292 | } 293 | } 294 | 295 | class TestCollectionOfPrimitives: Mappable { 296 | var dictStringString: [String: String] = [:] 297 | var dictStringInt: [String: Int] = [:] 298 | var dictStringBool: [String: Bool] = [:] 299 | var dictStringDouble: [String: Double] = [:] 300 | var dictStringFloat: [String: Float] = [:] 301 | 302 | var arrayString: [String] = [] 303 | var arrayInt: [Int] = [] 304 | var arrayBool: [Bool] = [] 305 | var arrayDouble: [Double] = [] 306 | var arrayFloat: [Float] = [] 307 | 308 | init(){ 309 | 310 | } 311 | 312 | required init?(map: Map){ 313 | if map["value"].value() == nil { 314 | 315 | } 316 | if map.JSON["value"] == nil { 317 | 318 | } 319 | } 320 | 321 | func mapping(map: Map) { 322 | dictStringString <- map["dictStringString"] 323 | dictStringBool <- map["dictStringBool"] 324 | dictStringInt <- map["dictStringInt"] 325 | dictStringDouble <- map["dictStringDouble"] 326 | dictStringFloat <- map["dictStringFloat"] 327 | arrayString <- map["arrayString"] 328 | arrayInt <- map["arrayInt"] 329 | arrayBool <- map["arrayBool"] 330 | arrayDouble <- map["arrayDouble"] 331 | arrayFloat <- map["arrayFloat"] 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/ClassClusterTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ClassClusterTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2015-09-18. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | import XCTest 31 | import ObjectMapper 32 | 33 | class ClassClusterTests: XCTestCase { 34 | 35 | override func setUp() { 36 | super.setUp() 37 | // Put setup code here. This method is called before the invocation of each test method in the class. 38 | } 39 | 40 | override func tearDown() { 41 | // Put teardown code here. This method is called after the invocation of each test method in the class. 42 | super.tearDown() 43 | } 44 | 45 | func testClassClusters() { 46 | let carName = "Honda" 47 | let JSON = ["name": carName, "type": "car"] 48 | 49 | if let vehicle = Mapper().map(JSON: JSON){ 50 | XCTAssertNotNil(vehicle) 51 | XCTAssertNotNil(vehicle as? Car) 52 | XCTAssertEqual((vehicle as? Car)?.name, carName) 53 | } 54 | } 55 | 56 | func testClassClustersFromJSONString() { 57 | let carName = "Honda" 58 | let JSON = "{\"name\": \"\(carName)\", \"type\": \"car\"}" 59 | 60 | if let vehicle = Mapper().map(JSONString: JSON){ 61 | XCTAssertNotNil(vehicle) 62 | XCTAssertNotNil(vehicle as? Car) 63 | XCTAssertEqual((vehicle as? Car)?.name, carName) 64 | } 65 | } 66 | 67 | func testClassClusterArray() { 68 | let carName = "Honda" 69 | let JSON = [["name": carName, "type": "car"], ["type": "bus"], ["type": "vehicle"]] 70 | 71 | let vehicles = Mapper().mapArray(JSONArray: JSON) 72 | XCTAssertNotNil(vehicles) 73 | XCTAssertTrue(vehicles.count == 3) 74 | XCTAssertNotNil(vehicles[0] as? Car) 75 | XCTAssertNotNil(vehicles[1] as? Bus) 76 | XCTAssertNotNil(vehicles[2]) 77 | XCTAssertEqual((vehicles[0] as? Car)?.name, carName) 78 | } 79 | } 80 | 81 | class Vehicle: StaticMappable { 82 | 83 | var type: String? 84 | 85 | class func objectForMapping(map: Map) -> BaseMappable? { 86 | if let type: String = map["type"].value() { 87 | switch type { 88 | case "car": 89 | return Car() 90 | case "bus": 91 | return Bus() 92 | default: 93 | return Vehicle() 94 | } 95 | } 96 | return nil 97 | } 98 | 99 | init(){ 100 | 101 | } 102 | 103 | func mapping(map: Map) { 104 | type <- map["type"] 105 | } 106 | } 107 | 108 | class Car: Vehicle { 109 | 110 | var name: String? 111 | 112 | override class func objectForMapping(map: Map) -> BaseMappable? { 113 | return nil 114 | } 115 | 116 | override func mapping(map: Map) { 117 | super.mapping(map: map) 118 | 119 | name <- map["name"] 120 | } 121 | } 122 | 123 | class Bus: Vehicle { 124 | 125 | override func mapping(map: Map) { 126 | super.mapping(map: map) 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/CodableTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CodableTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by Jari Kalinainen on 11.10.18. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | import XCTest 31 | import ObjectMapper 32 | 33 | class CodableTests: XCTestCase { 34 | 35 | override func setUp() { 36 | super.setUp() 37 | // Put setup code here. This method is called before the invocation of each test method in the class. 38 | } 39 | 40 | override func tearDown() { 41 | // Put teardown code here. This method is called after the invocation of each test method in the class. 42 | super.tearDown() 43 | } 44 | 45 | func testCodableTransform() { 46 | let value: [String: Any] = [ "one": "1", "two": 2, "three": true ] 47 | let JSON: [String: Any] = [ "value": value, "array_value": [value, value]] 48 | 49 | let mapper = Mapper() 50 | 51 | let object: ImmutableMappableObject! = mapper.map(JSON: JSON) 52 | XCTAssertNotNil(object) 53 | XCTAssertNil(object.nilValue) // without transform this is nil 54 | XCTAssertNotNil(object.value) 55 | XCTAssertNotNil(object.value?.one) 56 | XCTAssertNotNil(object.value?.two) 57 | XCTAssertNotNil(object.value?.three) 58 | XCTAssertNotNil(object.arrayValue) 59 | } 60 | } 61 | 62 | class ImmutableMappableObject: ImmutableMappable { 63 | 64 | var value: CodableModel? 65 | var arrayValue: [CodableModel]? 66 | var nilValue: CodableModel? 67 | 68 | required init(map: Map) throws { 69 | nilValue = try? map.value("value") 70 | value = try? map.value("value", using: CodableTransform()) 71 | arrayValue = try? map.value("array_value", using: CodableTransform<[CodableModel]>()) 72 | } 73 | 74 | func mapping(map: Map) { 75 | nilValue <- map["value"] 76 | value <- (map["value"], using: CodableTransform()) 77 | arrayValue <- (map["array_value"], using: CodableTransform<[CodableModel]>()) 78 | } 79 | } 80 | 81 | struct CodableModel: Codable { 82 | let one: String 83 | let two: Int 84 | let three: Bool 85 | } 86 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/CustomTransformTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomTransformTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2015-03-09. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | import XCTest 31 | import ObjectMapper 32 | 33 | #if os(iOS) || os(tvOS) || os(watchOS) 34 | typealias TestHexColor = UIColor 35 | #else 36 | typealias TestHexColor = NSColor 37 | #endif 38 | 39 | class CustomTransformTests: XCTestCase { 40 | 41 | let mapper = Mapper() 42 | 43 | override func setUp() { 44 | super.setUp() 45 | // Put setup code here. This method is called before the invocation of each test method in the class. 46 | } 47 | 48 | override func tearDown() { 49 | // Put teardown code here. This method is called after the invocation of each test method in the class. 50 | super.tearDown() 51 | } 52 | 53 | func testDateTransform() { 54 | let transforms = Transforms() 55 | transforms.date = Date(timeIntervalSince1970: 946684800) 56 | transforms.dateOpt = Date(timeIntervalSince1970: 946684912) 57 | transforms.dateMs = transforms.date 58 | transforms.dateOptMs = transforms.dateOpt 59 | 60 | let JSON = mapper.toJSON(transforms) 61 | let parsedTransforms = mapper.map(JSON: JSON) 62 | XCTAssertNotNil(parsedTransforms) 63 | XCTAssertEqual(parsedTransforms?.date, transforms.date) 64 | XCTAssertEqual(parsedTransforms?.dateOpt, transforms.dateOpt) 65 | XCTAssertEqual(parsedTransforms?.dateMs, transforms.dateMs) 66 | XCTAssertEqual(parsedTransforms?.dateOptMs, transforms.dateOptMs) 67 | 68 | let JSONDateString: [String: Any] = ["date": "946684800", "dateOpt": "946684912", 69 | "dateMs": "946684800000", "dateOptMs": "946684912000"] 70 | let parsedTransformsDateString = mapper.map(JSON: JSONDateString) 71 | 72 | XCTAssertNotNil(parsedTransformsDateString) 73 | XCTAssertEqual(parsedTransforms?.date, parsedTransformsDateString?.date) 74 | XCTAssertEqual(parsedTransforms?.dateOpt, parsedTransformsDateString?.dateOpt) 75 | XCTAssertEqual(parsedTransforms?.dateMs, parsedTransformsDateString?.dateMs) 76 | XCTAssertEqual(parsedTransforms?.dateOptMs, parsedTransformsDateString?.dateOptMs) 77 | 78 | } 79 | 80 | func testISO8601DateTransform() { 81 | let transforms = Transforms() 82 | transforms.ISO8601Date = Date(timeIntervalSince1970: 1398956159) 83 | transforms.ISO8601DateOpt = Date(timeIntervalSince1970: 1398956159) 84 | let JSON = mapper.toJSON(transforms) 85 | 86 | let parsedTransforms = mapper.map(JSON: JSON) 87 | XCTAssertNotNil(parsedTransforms) 88 | XCTAssertEqual(parsedTransforms?.ISO8601Date, transforms.ISO8601Date) 89 | XCTAssertEqual(parsedTransforms?.ISO8601DateOpt, transforms.ISO8601DateOpt) 90 | } 91 | 92 | func testISO8601DateTransformWithInvalidInput() { 93 | var JSON: [String: Any] = ["ISO8601Date": ""] 94 | let transforms = mapper.map(JSON: JSON) 95 | 96 | XCTAssertNil(transforms?.ISO8601DateOpt) 97 | 98 | JSON["ISO8601Date"] = "incorrect format" 99 | 100 | let transforms2 = mapper.map(JSON: JSON) 101 | 102 | XCTAssertNil(transforms2?.ISO8601DateOpt) 103 | } 104 | 105 | func testCustomFormatDateTransform(){ 106 | let dateString = "2015-03-03T02:36:44" 107 | let JSON: [String: Any] = ["customFormateDate": dateString] 108 | let transform: Transforms! = mapper.map(JSON: JSON) 109 | XCTAssertNotNil(transform) 110 | 111 | let JSONOutput = mapper.toJSON(transform) 112 | 113 | XCTAssertEqual(JSONOutput["customFormateDate"] as? String, dateString) 114 | } 115 | 116 | func testIntToStringTransformOf() { 117 | let intValue = 12345 118 | let JSON: [String: Any] = ["intWithString": "\(intValue)"] 119 | let transforms = mapper.map(JSON: JSON) 120 | 121 | XCTAssertEqual(transforms?.intWithString, intValue) 122 | } 123 | 124 | func testInt64MaxValue() { 125 | let transforms = Transforms() 126 | transforms.int64Value = INT64_MAX 127 | 128 | let JSON = mapper.toJSON(transforms) 129 | 130 | let parsedTransforms = mapper.map(JSON: JSON) 131 | XCTAssertNotNil(parsedTransforms) 132 | XCTAssertEqual(parsedTransforms?.int64Value, transforms.int64Value) 133 | } 134 | 135 | func testURLTranform() { 136 | let transforms = Transforms() 137 | transforms.URL = URL(string: "http://google.com/image/1234")! 138 | transforms.URLOpt = URL(string: "http://google.com/image/1234") 139 | transforms.URLWithoutEncoding = URL(string: "http://google.com/image/1234#fragment")! 140 | 141 | let JSON = mapper.toJSON(transforms) 142 | 143 | let parsedTransforms = mapper.map(JSON: JSON) 144 | 145 | XCTAssertNotNil(parsedTransforms) 146 | XCTAssertEqual(parsedTransforms?.URL, transforms.URL) 147 | XCTAssertEqual(parsedTransforms?.URLOpt, transforms.URLOpt) 148 | XCTAssertEqual(parsedTransforms?.URLWithoutEncoding, transforms.URLWithoutEncoding) 149 | } 150 | 151 | func testEnumTransform() { 152 | let JSON: [String: Any] = ["firstImageType": "cover", "secondImageType": "thumbnail"] 153 | let transforms = mapper.map(JSON: JSON) 154 | 155 | let imageType = Transforms.ImageType.self 156 | XCTAssertEqual(transforms?.firstImageType, imageType.Cover) 157 | XCTAssertEqual(transforms?.secondImageType, imageType.Thumbnail) 158 | } 159 | 160 | func testHexColorTransform() { 161 | let JSON: [String: Any] = [ 162 | "colorRed": "#FF0000", 163 | "colorGreenLowercase": "#00FF00", 164 | "colorBlueWithoutHash": "0000FF", 165 | "color3lenght": "F00", 166 | "color4lenght": "F00f", 167 | "color8lenght": "ff0000ff" 168 | ] 169 | 170 | let transform = mapper.map(JSON: JSON) 171 | 172 | XCTAssertEqual(transform?.colorRed, TestHexColor.red) 173 | XCTAssertEqual(transform?.colorGreenLowercase, TestHexColor.green) 174 | XCTAssertEqual(transform?.colorBlueWithoutHash, TestHexColor.blue) 175 | XCTAssertEqual(transform?.color3lenght, TestHexColor.red) 176 | XCTAssertEqual(transform?.color4lenght, TestHexColor.red) 177 | XCTAssertEqual(transform?.color8lenght, TestHexColor.red) 178 | 179 | let JSONOutput = mapper.toJSON(transform!) 180 | 181 | XCTAssertEqual(JSONOutput["colorRed"] as? String, "FF0000") 182 | XCTAssertEqual(JSONOutput["colorGreenLowercase"] as? String, "00FF00") 183 | XCTAssertEqual(JSONOutput["colorBlueWithoutHash"] as? String, "#0000FF") // prefixToJSON = true 184 | XCTAssertEqual(JSONOutput["color3lenght"] as? String, "FF0000") 185 | XCTAssertEqual(JSONOutput["color4lenght"] as? String, "FF0000") 186 | XCTAssertEqual(JSONOutput["color8lenght"] as? String, "FF0000FF") // alphaToJSON = true 187 | } 188 | } 189 | 190 | class Transforms: Mappable { 191 | 192 | internal enum ImageType: String { 193 | case Cover = "cover" 194 | case Thumbnail = "thumbnail" 195 | } 196 | 197 | var date = Date() 198 | var dateOpt: Date? 199 | 200 | var dateMs = Date() 201 | var dateOptMs: Date? 202 | 203 | var ISO8601Date: Date = Date() 204 | var ISO8601DateOpt: Date? 205 | 206 | var customFormatDate = Date() 207 | var customFormatDateOpt: Date? 208 | 209 | var URL = Foundation.URL(string: "") 210 | var URLOpt: Foundation.URL? 211 | var URLWithoutEncoding = Foundation.URL(string: "") 212 | 213 | var intWithString: Int = 0 214 | 215 | var int64Value: Int64 = 0 216 | 217 | var firstImageType: ImageType? 218 | var secondImageType: ImageType? 219 | 220 | var colorRed: TestHexColor? 221 | var colorGreenLowercase: TestHexColor? 222 | var colorBlueWithoutHash: TestHexColor? 223 | var color3lenght: TestHexColor? 224 | var color4lenght: TestHexColor? 225 | var color8lenght: TestHexColor? 226 | 227 | init(){ 228 | 229 | } 230 | 231 | required init?(map: Map){ 232 | 233 | } 234 | 235 | func mapping(map: Map) { 236 | date <- (map["date"], DateTransform()) 237 | dateOpt <- (map["dateOpt"], DateTransform()) 238 | 239 | dateMs <- (map["dateMs"], DateTransform(unit: .milliseconds)) 240 | dateOptMs <- (map["dateOptMs"], DateTransform(unit: .milliseconds)) 241 | 242 | ISO8601Date <- (map["ISO8601Date"], ISO8601DateTransform()) 243 | ISO8601DateOpt <- (map["ISO8601DateOpt"], ISO8601DateTransform()) 244 | 245 | customFormatDate <- (map["customFormateDate"], CustomDateFormatTransform(formatString: "yyyy-MM-dd'T'HH:mm:ss")) 246 | customFormatDateOpt <- (map["customFormateDateOpt"], CustomDateFormatTransform(formatString: "yyyy-MM-dd'T'HH:mm:ss")) 247 | 248 | URL <- (map["URL"], URLTransform()) 249 | URLOpt <- (map["URLOpt"], URLTransform()) 250 | URLWithoutEncoding <- (map["URLWithoutEncoding"], URLTransform(shouldEncodeURLString: false)) 251 | 252 | intWithString <- (map["intWithString"], TransformOf(fromJSON: { $0 == nil ? nil : Int($0!) }, toJSON: { $0.map { String($0) } })) 253 | int64Value <- (map["int64Value"], TransformOf(fromJSON: { $0?.int64Value }, toJSON: { $0.map { NSNumber(value: $0) } })) 254 | 255 | firstImageType <- (map["firstImageType"], EnumTransform()) 256 | secondImageType <- (map["secondImageType"], EnumTransform()) 257 | 258 | colorRed <- (map["colorRed"], HexColorTransform()) 259 | colorGreenLowercase <- (map["colorGreenLowercase"], HexColorTransform()) 260 | colorBlueWithoutHash <- (map["colorBlueWithoutHash"], HexColorTransform(prefixToJSON: true)) 261 | color3lenght <- (map["color3lenght"], HexColorTransform()) 262 | color4lenght <- (map["color4lenght"], HexColorTransform()) 263 | color8lenght <- (map["color8lenght"], HexColorTransform(alphaToJSON: true)) 264 | } 265 | } 266 | 267 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/DataTransformTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSDataTransformTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by Yagrushkin, Evgeny on 8/30/16. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import XCTest 30 | import ObjectMapper 31 | 32 | class DataTransformTests: XCTestCase { 33 | 34 | let mapper = Mapper() 35 | 36 | func testDataTransform() { 37 | 38 | let dataLength = 20 39 | let bytes = malloc(dataLength) 40 | 41 | let data = Data(bytes: bytes!, count: dataLength) 42 | let dataString = data.base64EncodedString() 43 | let JSONString = "{\"data\" : \"\(dataString)\"}" 44 | 45 | let mappedObject = mapper.map(JSONString: JSONString) 46 | 47 | XCTAssertNotNil(mappedObject) 48 | XCTAssertEqual(mappedObject?.stringData, dataString) 49 | XCTAssertEqual(mappedObject?.data, data) 50 | } 51 | 52 | } 53 | 54 | class DataType: Mappable { 55 | 56 | var data: Data? 57 | var stringData: String? 58 | 59 | init(){ 60 | 61 | } 62 | 63 | required init?(map: Map){ 64 | 65 | } 66 | 67 | func mapping(map: Map) { 68 | stringData <- map["data"] 69 | data <- (map["data"], DataTransform()) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/DictionaryTransformTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DictionaryTransformTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by Milen Halachev on 7/20/16. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | import XCTest 31 | import ObjectMapper 32 | 33 | class DictionaryTransformTests: XCTestCase { 34 | 35 | func testDictionaryTransform() { 36 | 37 | let JSON = "{\"dictionary\":{\"1\":{\"foo\":\"uno\",\"bar\":1},\"two\":{\"foo\":\"dve\",\"bar\":2},\"bar\":{\"foo\":\"bar\",\"bar\":777}}}" 38 | 39 | guard let result = DictionaryTransformTestsObject(JSONString: JSON) else { 40 | 41 | XCTFail("Unable to parse the JSON") 42 | return 43 | } 44 | 45 | XCTAssertEqual(result.dictionary.count, 3) 46 | 47 | XCTAssertEqual(result.dictionary[.One]?.foo, "uno") 48 | XCTAssertEqual(result.dictionary[.One]?.bar, 1) 49 | 50 | XCTAssertEqual(result.dictionary[.Two]?.foo, "dve") 51 | XCTAssertEqual(result.dictionary[.Two]?.bar, 2) 52 | 53 | XCTAssertEqual(result.dictionary[.Foo]?.foo, "bar") 54 | XCTAssertEqual(result.dictionary[.Foo]?.bar, 777) 55 | } 56 | } 57 | 58 | class DictionaryTransformTestsObject: Mappable { 59 | 60 | var dictionary: [MyKey: MyValue] = [:] 61 | 62 | required init?(map: Map) { 63 | 64 | 65 | } 66 | 67 | func mapping(map: Map) { 68 | 69 | self.dictionary <- (map["dictionary"], DictionaryTransform()) 70 | } 71 | } 72 | 73 | extension DictionaryTransformTestsObject { 74 | 75 | enum MyKey: String { 76 | 77 | case One = "1" 78 | case Two = "two" 79 | case Foo = "bar" 80 | } 81 | } 82 | 83 | extension DictionaryTransformTestsObject { 84 | 85 | class MyValue: Mappable { 86 | 87 | var foo: String 88 | var bar: Int 89 | 90 | required init?(map: Map) { 91 | 92 | self.foo = "__foo" 93 | self.bar = self.foo.hash 94 | 95 | self.mapping(map: map) 96 | 97 | guard self.foo != "__foo" && self.bar != self.foo.hash else { 98 | 99 | return nil 100 | } 101 | } 102 | 103 | func mapping(map: Map) { 104 | 105 | self.foo <- map["foo"] 106 | self.bar <- map["bar"] 107 | } 108 | } 109 | } 110 | 111 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/GenericObjectsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GenericObjectsTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2016-09-26. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import XCTest 30 | import ObjectMapper 31 | 32 | class GenericObjectsTests: XCTestCase { 33 | 34 | override func setUp() { 35 | super.setUp() 36 | // Put setup code here. This method is called before the invocation of each test method in the class. 37 | } 38 | 39 | override func tearDown() { 40 | // Put teardown code here. This method is called after the invocation of each test method in the class. 41 | super.tearDown() 42 | } 43 | 44 | func testSubclass() { 45 | let object = Subclass() 46 | object.base = "base var" 47 | object.sub = "sub var" 48 | 49 | let json = Mapper().toJSON(object) 50 | let parsedObject = Mapper().map(JSON: json) 51 | 52 | XCTAssertEqual(object.base, parsedObject?.base) 53 | XCTAssertEqual(object.sub, parsedObject?.sub) 54 | } 55 | 56 | func testGenericSubclass() { 57 | let object = GenericSubclass() 58 | object.base = "base var" 59 | object.sub = "sub var" 60 | 61 | let json = Mapper().toJSON(object) 62 | let parsedObject = Mapper>().map(JSON: json) 63 | 64 | XCTAssertEqual(object.base, parsedObject?.base) 65 | XCTAssertEqual(object.sub, parsedObject?.sub) 66 | } 67 | 68 | func testSubclassWithGenericArrayInSuperclass() { 69 | let JSONString = "{\"genericItems\":[{\"value\":\"value0\"}, {\"value\":\"value1\"}]}" 70 | 71 | let parsedObject = Mapper>().map(JSONString: JSONString) 72 | 73 | let genericItems = parsedObject?.genericItems 74 | 75 | XCTAssertNotNil(genericItems) 76 | XCTAssertEqual(genericItems?[0].value, "value0") 77 | XCTAssertEqual(genericItems?[1].value, "value1") 78 | } 79 | 80 | 81 | func testMappingAGenericObject(){ 82 | let code: Int = 22 83 | let JSONString = "{\"result\":{\"code\":\(code)}}" 84 | 85 | let response = Mapper>().map(JSONString: JSONString) 86 | 87 | let status = response?.result?.status 88 | 89 | XCTAssertNotNil(status) 90 | XCTAssertEqual(status, code) 91 | } 92 | 93 | 94 | func testMappingAGenericObjectViaMappableExtension(){ 95 | let code: Int = 22 96 | let JSONString = "{\"result\":{\"code\":\(code)}}" 97 | 98 | let response = Response(JSONString: JSONString) 99 | 100 | let status = response?.result?.status 101 | 102 | XCTAssertNotNil(status) 103 | XCTAssertEqual(status, code) 104 | } 105 | 106 | } 107 | 108 | class Base: Mappable { 109 | 110 | var base: String? 111 | 112 | init(){ 113 | 114 | } 115 | 116 | required init?(map: Map){ 117 | 118 | } 119 | 120 | func mapping(map: Map) { 121 | base <- map["base"] 122 | } 123 | } 124 | 125 | class Subclass: Base { 126 | 127 | var sub: String? 128 | 129 | override init(){ 130 | super.init() 131 | } 132 | 133 | required init?(map: Map){ 134 | super.init(map: map) 135 | } 136 | 137 | override func mapping(map: Map) { 138 | super.mapping(map: map) 139 | 140 | sub <- map["sub"] 141 | } 142 | } 143 | 144 | 145 | class GenericSubclass: Base { 146 | 147 | var sub: String? 148 | 149 | override init(){ 150 | super.init() 151 | } 152 | 153 | required init?(map: Map){ 154 | super.init(map: map) 155 | } 156 | 157 | override func mapping(map: Map) { 158 | super.mapping(map: map) 159 | 160 | sub <- map["sub"] 161 | } 162 | } 163 | 164 | class WithGenericArray: Mappable { 165 | var genericItems: [T]? 166 | 167 | required init?(map: Map){ 168 | 169 | } 170 | 171 | func mapping(map: Map) { 172 | genericItems <- map["genericItems"] 173 | } 174 | } 175 | 176 | class ConcreteItem: Mappable { 177 | var value: String? 178 | 179 | required init?(map: Map){ 180 | 181 | } 182 | 183 | func mapping(map: Map) { 184 | value <- map["value"] 185 | } 186 | } 187 | 188 | class SubclassWithGenericArrayInSuperclass: WithGenericArray { 189 | required init?(map: Map){ 190 | super.init(map: map) 191 | } 192 | } 193 | 194 | class Response: Mappable { 195 | var result: T? 196 | 197 | required init?(map: Map){ 198 | 199 | } 200 | 201 | func mapping(map: Map) { 202 | result <- map["result"] 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/IgnoreNilTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IgnoreNilTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2016-06-06. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import XCTest 30 | import ObjectMapper 31 | 32 | class IgnoreNilTests: XCTestCase { 33 | 34 | override func setUp() { 35 | super.setUp() 36 | // Put setup code here. This method is called before the invocation of each test method in the class. 37 | } 38 | 39 | override func tearDown() { 40 | // Put teardown code here. This method is called after the invocation of each test method in the class. 41 | super.tearDown() 42 | } 43 | 44 | func testIgnoreNullField(){ 45 | let name = "Tristan" 46 | var user = User() 47 | user.name = name 48 | 49 | let JSON = "{\"name\" : null}" 50 | user = Mapper().map(JSONString: JSON, toObject: user) 51 | 52 | XCTAssertEqual(user.name, name) 53 | } 54 | 55 | func testIgnoreNilField(){ 56 | let name = "Tristan" 57 | var user = User() 58 | user.name = name 59 | 60 | let JSON = "{\"name\" : nil}" 61 | user = Mapper().map(JSONString: JSON, toObject: user) 62 | 63 | XCTAssertEqual(user.name, name) 64 | } 65 | 66 | private class User: Mappable { 67 | var name: String? 68 | 69 | init(){} 70 | 71 | required init?(map: Map){ 72 | 73 | } 74 | 75 | func mapping(map: Map){ 76 | name <- map["name", ignoreNil: true] 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/MapContextTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MapContextTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2016-05-10. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import XCTest 30 | import ObjectMapper 31 | 32 | class MapContextTests: XCTestCase { 33 | 34 | override func setUp() { 35 | super.setUp() 36 | // Put setup code here. This method is called before the invocation of each test method in the class. 37 | } 38 | 39 | override func tearDown() { 40 | // Put teardown code here. This method is called after the invocation of each test method in the class. 41 | super.tearDown() 42 | } 43 | 44 | // MARK: - BaseMappable 45 | // MARK: Single 46 | func testMappingWithContext() { 47 | let JSON = ["name": "Tristan"] 48 | let context = Context(shouldMap: true) 49 | 50 | let person = Mapper(context: context).map(JSON: JSON) 51 | 52 | XCTAssertNotNil(person) 53 | XCTAssertNotNil(person?.name) 54 | } 55 | 56 | func testMappingWithContextViaMappableExtension() { 57 | let JSON = ["name": "Tristan"] 58 | let context = Context(shouldMap: true) 59 | 60 | let person = Person(JSON: JSON, context: context) 61 | 62 | XCTAssertNotNil(person) 63 | XCTAssertNotNil(person?.name) 64 | } 65 | 66 | func testMappingWithoutContext() { 67 | let JSON = ["name": "Tristan"] 68 | 69 | let person = Mapper().map(JSON: JSON) 70 | 71 | XCTAssertNotNil(person) 72 | XCTAssertNil(person?.name) 73 | } 74 | 75 | // MARK: Nested 76 | func testNestedMappingWithContext() { 77 | let JSON = ["person": ["name": "Tristan"]] 78 | let context = Context(shouldMap: true) 79 | 80 | let nestedPerson = Mapper(context: context).map(JSON: JSON) 81 | 82 | XCTAssertNotNil(nestedPerson) 83 | XCTAssertNotNil(nestedPerson?.person?.name) 84 | } 85 | 86 | func testNestedMappingWithContextViaMappableExtension() { 87 | let JSON = ["person": ["name": "Tristan"]] 88 | let context = Context(shouldMap: true) 89 | 90 | let nestedPerson = NestedPerson(JSON: JSON, context: context) 91 | 92 | XCTAssertNotNil(nestedPerson) 93 | XCTAssertNotNil(nestedPerson?.person?.name) 94 | } 95 | 96 | func testNestedMappingWithoutContext() { 97 | let JSON = ["person": ["name": "Tristan"]] 98 | 99 | let nestedPerson = Mapper().map(JSON: JSON) 100 | 101 | XCTAssertNotNil(nestedPerson) 102 | XCTAssertNil(nestedPerson?.person?.name) 103 | } 104 | 105 | // MARK: Array 106 | func testArrayMappingWithContext() { 107 | let JSON = ["persons": [["name": "Tristan"], ["name": "Anton"]]] 108 | let context = Context(shouldMap: true) 109 | 110 | let person = Mapper(context: context).map(JSON: JSON) 111 | 112 | XCTAssertNotNil(person) 113 | XCTAssertNotNil(person?.persons) 114 | } 115 | 116 | func testArrayMappingWithContextViaMappableExtension() { 117 | let JSON = ["persons": [["name": "Tristan"], ["name": "Anton"]]] 118 | let context = Context(shouldMap: true) 119 | 120 | let person = PersonList(JSON: JSON, context: context) 121 | 122 | XCTAssertNotNil(person) 123 | XCTAssertNotNil(person?.persons) 124 | } 125 | 126 | func testArrayMappingWithoutContext() { 127 | let JSON = ["persons": [["name": "Tristan"], ["name": "Anton"]]] 128 | 129 | let person = Mapper().map(JSON: JSON) 130 | 131 | XCTAssertNotNil(person) 132 | XCTAssertNil(person?.persons) 133 | } 134 | 135 | // MARK: ImmutableMappable 136 | // MARK: Single 137 | func testImmutableMappingWithContext() { 138 | let JSON = ["name": "Anton"] 139 | let context = ImmutableContext(isDeveloper: true) 140 | 141 | let person = try? Mapper(context: context).map(JSON: JSON) 142 | 143 | XCTAssertNotNil(person) 144 | 145 | XCTAssertEqual(person?.isDeveloper ?? !context.isDeveloper, context.isDeveloper) 146 | } 147 | 148 | func testImmutableMappingWithContextViaMappableExtension() { 149 | let JSON = ["name": "Anton"] 150 | let context = ImmutableContext(isDeveloper: true) 151 | 152 | let person = try? ImmutablePerson(JSON: JSON, context: context) 153 | 154 | XCTAssertNotNil(person) 155 | XCTAssertEqual(person?.isDeveloper ?? !context.isDeveloper, context.isDeveloper) 156 | } 157 | 158 | func testImmutableMappingWithoutContext() { 159 | let JSON = ["name": "Anton"] 160 | 161 | do { 162 | let _ = try Mapper().map(JSON: JSON) 163 | } catch ImmutablePersonMappingError.contextAbsense { 164 | // Empty 165 | } catch { 166 | XCTFail() 167 | } 168 | } 169 | 170 | // MARK: Nested 171 | func testNestedImmutableMappingWithContext() { 172 | let JSON = ["person": ["name": "Anton"]] 173 | let context = ImmutableContext(isDeveloper: true) 174 | 175 | let nestedPerson = try? Mapper(context: context).map(JSON: JSON) 176 | 177 | XCTAssertNotNil(nestedPerson) 178 | XCTAssertEqual(nestedPerson?.person.isDeveloper ?? !context.isDeveloper, context.isDeveloper) 179 | } 180 | 181 | func testNestedImmutableMappingWithContextViaMappableExtension() { 182 | let JSON = ["person": ["name": "Anton"]] 183 | let context = ImmutableContext(isDeveloper: true) 184 | 185 | let nestedPerson = try? ImmutableNestedPerson(JSON: JSON, context: context) 186 | 187 | XCTAssertNotNil(nestedPerson) 188 | XCTAssertEqual(nestedPerson?.person.isDeveloper ?? !context.isDeveloper, context.isDeveloper) 189 | } 190 | 191 | func testNestedImmutableMappingWithoutContext() { 192 | let JSON = ["person": ["name": "Anton"]] 193 | 194 | do { 195 | let _ = try Mapper().map(JSON: JSON) 196 | } catch ImmutablePersonMappingError.contextAbsense { 197 | return 198 | } catch { 199 | XCTFail() 200 | } 201 | 202 | XCTFail() 203 | } 204 | 205 | // MARK: Array 206 | func testArrayImmutableMappingWithContext() { 207 | let JSON = ["persons": [["name": "Tristan"], ["name": "Anton"]]] 208 | let context = ImmutableContext(isDeveloper: true) 209 | 210 | let personList = try? Mapper(context: context).map(JSON: JSON) 211 | 212 | XCTAssertNotNil(personList) 213 | 214 | personList?.persons.forEach { person in 215 | XCTAssertEqual(person.isDeveloper, context.isDeveloper) 216 | } 217 | } 218 | 219 | func testArrayImmutableMappingWithContextViaMappableExtension() { 220 | let JSON = ["persons": [["name": "Tristan"], ["name": "Anton"]]] 221 | let context = ImmutableContext(isDeveloper: true) 222 | 223 | let personList = try? ImmutablePersonList(JSON: JSON, context: context) 224 | 225 | XCTAssertNotNil(personList) 226 | 227 | personList?.persons.forEach { person in 228 | XCTAssertEqual(person.isDeveloper, context.isDeveloper) 229 | } 230 | } 231 | 232 | func testArrayImmutableMappingWithoutContext() { 233 | let JSON = ["persons": [["name": "Tristan"], ["name": "Anton"]]] 234 | 235 | do { 236 | let _ = try Mapper().map(JSON: JSON) 237 | } catch ImmutablePersonMappingError.contextAbsense { 238 | return 239 | } catch { 240 | XCTFail() 241 | } 242 | 243 | XCTFail() 244 | } 245 | 246 | func testDefaultArgumentWithoutValue() { 247 | let JSON: [String: Any] = [:] 248 | let dog = try? Mapper().map(JSON: JSON) as ImmutableDog 249 | 250 | XCTAssertNotNil(dog) 251 | XCTAssertTrue(dog!.name == "Sasha") 252 | } 253 | 254 | func testDefaultArgumentWithValue() { 255 | let JSON = ["name": "Sofie"] 256 | let dog = try? Mapper().map(JSON: JSON) as ImmutableDog 257 | 258 | XCTAssertNotNil(dog) 259 | XCTAssertTrue(dog!.name == "Sofie") 260 | } 261 | 262 | // MARK: - Default Argument 263 | public struct ImmutableDog: ImmutableMappable { 264 | public let name: String 265 | 266 | /// Define `default` value to use if it is nothing to parse in `name` 267 | public init(map: Map) throws { 268 | name = try map.value("name", default: "Sasha") 269 | } 270 | } 271 | 272 | // MARK: - Nested Types 273 | // MARK: BaseMappable 274 | struct Context: MapContext { 275 | var shouldMap = false 276 | 277 | init(shouldMap: Bool){ 278 | self.shouldMap = shouldMap 279 | } 280 | } 281 | 282 | class Person: Mappable { 283 | var name: String? 284 | 285 | required init?(map: Map){ 286 | 287 | } 288 | 289 | func mapping(map: Map) { 290 | if (map.context as? Context)?.shouldMap == true { 291 | name <- map["name"] 292 | } 293 | } 294 | } 295 | 296 | class NestedPerson: Mappable { 297 | var person: Person? 298 | 299 | required init?(map: Map){ 300 | 301 | } 302 | 303 | func mapping(map: Map) { 304 | if (map.context as? Context)?.shouldMap == true { 305 | person <- map["person"] 306 | } 307 | } 308 | } 309 | 310 | class PersonList: Mappable { 311 | var persons: [Person]? 312 | 313 | required init?(map: Map){ 314 | 315 | } 316 | 317 | func mapping(map: Map) { 318 | if (map.context as? Context)?.shouldMap == true { 319 | persons <- map["persons"] 320 | } 321 | } 322 | } 323 | 324 | // MARK: ImmutableMappable 325 | struct ImmutableContext: MapContext { 326 | let isDeveloper: Bool 327 | } 328 | 329 | enum ImmutablePersonMappingError: Error { 330 | case contextAbsense 331 | } 332 | 333 | struct ImmutablePerson: ImmutableMappable { 334 | let name: String 335 | let isDeveloper: Bool 336 | 337 | init(map: Map) throws { 338 | guard let context = map.context as? ImmutableContext else { 339 | throw ImmutablePersonMappingError.contextAbsense 340 | } 341 | 342 | name = try map.value("name") 343 | isDeveloper = context.isDeveloper 344 | } 345 | } 346 | 347 | struct ImmutableNestedPerson: ImmutableMappable { 348 | let person: ImmutablePerson 349 | 350 | init(map: Map) throws { 351 | person = try map.value("person") 352 | } 353 | } 354 | 355 | struct ImmutablePersonList: ImmutableMappable { 356 | let persons: [ImmutablePerson] 357 | 358 | init(map: Map) throws { 359 | persons = try map.value("persons") 360 | } 361 | } 362 | } 363 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/MappableExtensionsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MappableExtensionsTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by Scott Hoyt on 10/25/15. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | import XCTest 31 | import ObjectMapper 32 | 33 | struct TestMappable: Mappable, Equatable, Hashable { 34 | static let valueForString = "This string should work" 35 | static let workingJSONString = "{ \"value\" : \"\(valueForString)\" }" 36 | static let workingJSON: [String: Any] = ["value": valueForString] 37 | static let workingJSONArrayString = "[\(workingJSONString)]" 38 | 39 | var value: String? 40 | 41 | init() {} 42 | init?(map: Map) { } 43 | 44 | mutating func mapping(map: Map) { 45 | value <- map["value"] 46 | } 47 | 48 | var hashValue: Int { 49 | if let value = value { 50 | return value.hashValue 51 | } 52 | return NSIntegerMax 53 | } 54 | } 55 | 56 | func ==(lhs: TestMappable, rhs: TestMappable) -> Bool { 57 | return lhs.value == rhs.value 58 | } 59 | 60 | class MappableExtensionsTests: XCTestCase { 61 | 62 | var testMappable: TestMappable! 63 | 64 | override func setUp() { 65 | super.setUp() 66 | testMappable = TestMappable() 67 | testMappable.value = TestMappable.valueForString 68 | } 69 | 70 | func testInitFromString() { 71 | let mapped = TestMappable(JSONString: TestMappable.workingJSONString) 72 | 73 | XCTAssertNotNil(mapped) 74 | XCTAssertEqual(mapped?.value, TestMappable.valueForString) 75 | } 76 | 77 | func testToJSONAndBack() { 78 | let mapped = TestMappable(JSON: testMappable.toJSON()) 79 | XCTAssertEqual(mapped, testMappable) 80 | } 81 | 82 | func testArrayFromString() { 83 | let mapped = [TestMappable](JSONString: TestMappable.workingJSONArrayString)! 84 | XCTAssertEqual(mapped, [testMappable]) 85 | } 86 | 87 | func testArrayToJSONAndBack() { 88 | let mapped = [TestMappable](JSONArray: [testMappable].toJSON()) 89 | XCTAssertEqual(mapped, [testMappable]) 90 | } 91 | 92 | func testSetInitFailsWithEmptyString() { 93 | XCTAssertNil(Set(JSONString: "")) 94 | } 95 | 96 | func testSetFromString() { 97 | let mapped = Set(JSONString: TestMappable.workingJSONArrayString)! 98 | XCTAssertEqual(mapped, Set([testMappable])) 99 | } 100 | 101 | func testSetToJSONAndBack() { 102 | let mapped = Set(JSONArray: Set([testMappable]).toJSON()) 103 | XCTAssertEqual(mapped, [testMappable]) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/MappableTypesWithTransformsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MappableTypesWithTransformsTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by Paddy O'Brien on 2015-12-04. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import XCTest 30 | import ObjectMapper 31 | 32 | 33 | class MappableTypesWithTransformsTests: XCTestCase { 34 | // This is a func so that it can be collapsed 35 | func JSONPayload() -> [String: Any] { 36 | return [ 37 | "teams": [[ 38 | "api_uri": "/teams/8", 39 | "full_name": "Team Secret", 40 | "short_name": "Secret", 41 | "players": ["/players/1", "/players/2", "/players/3", "/players/4", "/players/5"] 42 | ], [ 43 | "api_uri": "/teams/43", 44 | "full_name": "Mineski", 45 | "short_name": "Mski", 46 | "players": ["/players/6", "/players/7", "/players/8", "/players/9", "/players/10"] 47 | ]], 48 | "game": [ 49 | "api_uri": "/games/2723", 50 | "game_time": "33:49", 51 | "players": [ 52 | ["/players/1", "/players/2", "/players/3", "/players/4", "/players/5"], 53 | ["/players/6", "/players/7", "/players/8", "/players/9", "/players/10"] 54 | ], 55 | "team1_lineup": [ 56 | "top": "/players/1", 57 | "mid": "/players/2", 58 | "bottom": "/players/3", 59 | "support": "/players/4", 60 | "carry": "/players/5" 61 | ], 62 | "team2_lineup": [ 63 | "top": "/players/6", 64 | "mid": "/players/7", 65 | "bottom": "/players/8", 66 | "support": "/players/9", 67 | "carry": "/players/10" 68 | ], 69 | "head_to_head": [ 70 | "top": ["/players/1", "/players/6"], 71 | "mid": ["/players/2", "/players/7"], 72 | "bottom": ["/players/3", "/players/8"], 73 | "support": ["/players/4", "/players/9"], 74 | "carry": ["/players/5", "/players/10"] 75 | ], 76 | "teams": ["/teams/43", "/teams/8"], 77 | "winning_team_url": "/teams/8" 78 | ] 79 | ] 80 | } 81 | 82 | 83 | // MARK: - Non-Optional Tests 84 | func testParsingSingleInstanceWithTransform() { 85 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 86 | 87 | XCTAssertNotNil(game) 88 | XCTAssertNotEqual(game!.winner.URI, "FAKE") 89 | } 90 | 91 | func testParsingArrayOfObjectsWithTransform() { 92 | let teams = Mapper().mapArray(JSONObject: JSONPayload()["teams"]) 93 | 94 | XCTAssertNotNil(teams) 95 | XCTAssertNotEqual(teams!.count, 0) 96 | 97 | XCTAssertNotEqual(teams!.first!.players.count, 0) 98 | } 99 | 100 | func testParsing2DimensionalArrayOfObjectsWithTransform() { 101 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 102 | 103 | XCTAssertNotNil(game) 104 | XCTAssertNotEqual(game!.players.count, 0) 105 | XCTAssertNotEqual(game!.players.first!.count, 0) 106 | XCTAssertNotEqual(game!.players.last!.count, 0) 107 | } 108 | 109 | func testParsingDictionaryOfObjectsWithTransform() { 110 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 111 | 112 | XCTAssertNotNil(game) 113 | XCTAssertNotEqual(game!.team1Lineup.count, 0) 114 | XCTAssertNotEqual(game!.team2Lineup.count, 0) 115 | } 116 | 117 | func testParsingDictionaryOfArrayOfObjectsWithTransform() { 118 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 119 | 120 | XCTAssertNotNil(game) 121 | for (position, players) in game!.headToHead { 122 | XCTAssertNotEqual(players.count, 0, "No players were mapped for \(position)") 123 | } 124 | } 125 | 126 | func testParsingSetOfObjectsWithTransform() { 127 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 128 | 129 | XCTAssertNotNil(game) 130 | XCTAssertNotEqual(game!.teams.count, 0) 131 | } 132 | 133 | 134 | // MARK: - Optional Tests 135 | func testParsingOptionalSingleInstanceWithTransform() { 136 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 137 | 138 | XCTAssertNotNil(game) 139 | XCTAssertNotNil(game!.O_winner) 140 | } 141 | 142 | func testParsingOptionalArrayOfObjectsWithTransform() { 143 | let teams = Mapper().mapArray(JSONObject: JSONPayload()["teams"]) 144 | 145 | XCTAssertNotNil(teams) 146 | XCTAssertNotEqual(teams!.count, 0) 147 | 148 | XCTAssertNotNil(teams!.first!.O_players) 149 | XCTAssertNotEqual(teams!.first!.O_players!.count, 0) 150 | } 151 | 152 | func testParsingOptional2DimensionalArrayOfObjectsWithTransform() { 153 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 154 | 155 | XCTAssertNotNil(game) 156 | XCTAssertNotNil(game!.O_players) 157 | XCTAssertNotEqual(game!.O_players!.count, 0) 158 | XCTAssertNotEqual(game!.O_players!.first!.count, 0) 159 | XCTAssertNotEqual(game!.O_players!.last!.count, 0) 160 | } 161 | 162 | func testParsingOptionalDictionaryOfObjectsWithTransform() { 163 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 164 | 165 | XCTAssertNotNil(game) 166 | XCTAssertNotNil(game!.O_team1Lineup) 167 | XCTAssertNotEqual(game!.O_team1Lineup!.count, 0) 168 | XCTAssertNotNil(game!.O_team2Lineup) 169 | XCTAssertNotEqual(game!.O_team2Lineup!.count, 0) 170 | } 171 | 172 | func testParsingOptionalDictionaryOfArrayOfObjectsWithTransform() { 173 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 174 | 175 | XCTAssertNotNil(game) 176 | XCTAssertNotNil(game!.O_headToHead) 177 | for (position, players) in game!.O_headToHead! { 178 | XCTAssertNotEqual(players.count, 0, "No players were mapped for \(position)") 179 | } 180 | } 181 | 182 | func testParsingOptionalSetOfObjectsWithTransform() { 183 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 184 | 185 | XCTAssertNotNil(game) 186 | XCTAssertNotNil(game!.O_teams) 187 | XCTAssertNotEqual(game!.O_teams!.count, 0) 188 | } 189 | 190 | // MARK: - Implicitly Unwrapped Optional Tests 191 | func testParsingImplicitlyUnwrappedSingleInstanceWithTransform() { 192 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 193 | 194 | XCTAssertNotNil(game) 195 | XCTAssertNotNil(game!.I_winner) 196 | } 197 | 198 | func testParsingImplicitlyUnwrappedArrayOfObjectsWithTransform() { 199 | let teams = Mapper().mapArray(JSONObject: JSONPayload()["teams"]) 200 | 201 | XCTAssertNotNil(teams) 202 | XCTAssertNotEqual(teams!.count, 0) 203 | 204 | XCTAssertNotNil(teams!.first!.I_players) 205 | XCTAssertNotEqual(teams!.first!.I_players!.count, 0) 206 | } 207 | 208 | func testParsingImplicitlyUnwrapped2DimensionalArrayOfObjectsWithTransform() { 209 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 210 | 211 | XCTAssertNotNil(game) 212 | XCTAssertNotNil(game!.I_players) 213 | XCTAssertNotEqual(game!.I_players!.count, 0) 214 | XCTAssertNotEqual(game!.I_players!.first!.count, 0) 215 | XCTAssertNotEqual(game!.I_players!.last!.count, 0) 216 | } 217 | 218 | func testParsingImplicitlyUnwrappedDictionaryOfObjectsWithTransform() { 219 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 220 | 221 | XCTAssertNotNil(game) 222 | XCTAssertNotNil(game!.I_team1Lineup) 223 | XCTAssertNotEqual(game!.I_team1Lineup!.count, 0) 224 | XCTAssertNotNil(game!.I_team2Lineup) 225 | XCTAssertNotEqual(game!.I_team2Lineup!.count, 0) 226 | } 227 | 228 | func testParsingImplicitlyUnwrappedDictionaryOfArrayOfObjectsWithTransform() { 229 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 230 | 231 | XCTAssertNotNil(game) 232 | XCTAssertNotNil(game!.I_headToHead) 233 | for (position, players) in game!.I_headToHead! { 234 | XCTAssertNotEqual(players.count, 0, "No players were mapped for \(position)") 235 | } 236 | } 237 | 238 | func testParsingImplicitlyUnwrappedSetOfObjectsWithTransform() { 239 | let game = Mapper().map(JSONObject: JSONPayload()["game"]) 240 | 241 | XCTAssertNotNil(game) 242 | XCTAssertNotNil(game!.I_teams) 243 | XCTAssertNotEqual(game!.I_teams!.count, 0) 244 | } 245 | 246 | // MARK: - Internal classes for testing 247 | class Game: Mappable, URIInitiable { 248 | var URI: String? 249 | var players: [[Player]] = [[]] 250 | var team1Lineup: [String: Player] = [:] 251 | var team2Lineup: [String: Player] = [:] 252 | var headToHead: [String: [Player]] = [:] 253 | var teams: Set = [] 254 | var winner: Team = Team(URI: "FAKE") 255 | 256 | // Optional 257 | var O_players: [[Player]]? 258 | var O_team1Lineup: [String: Player]? 259 | var O_team2Lineup: [String: Player]? 260 | var O_headToHead: [String: [Player]]? 261 | var O_teams: Set? 262 | var O_winner: Team? 263 | 264 | // Implicitly Unwrapped 265 | var I_players: [[Player]]! 266 | var I_team1Lineup: [String: Player]! 267 | var I_team2Lineup: [String: Player]! 268 | var I_headToHead: [String: [Player]]! 269 | var I_teams: Set! 270 | var I_winner: Team! 271 | 272 | required init(URI: String) { self.URI = URI } 273 | required init?(map: Map) {} 274 | 275 | func mapping(map: Map) { 276 | players <- (map["players"], RelationshipTransform()) // 2D Array with transform 277 | team1Lineup <- (map["team1_lineup"], RelationshipTransform()) // Dictionary with transform 278 | team2Lineup <- (map["team1_lineup"], RelationshipTransform()) 279 | headToHead <- (map["head_to_head"], RelationshipTransform()) // Dictionary of arrays with transform 280 | teams <- (map["teams"], RelationshipTransform()) // Set with transform 281 | winner <- (map["winning_team_url"], RelationshipTransform()) // Single instance with transform 282 | 283 | // Optional 284 | O_players <- (map["players"], RelationshipTransform()) 285 | O_team1Lineup <- (map["team1_lineup"], RelationshipTransform()) 286 | O_team2Lineup <- (map["team1_lineup"], RelationshipTransform()) 287 | O_headToHead <- (map["head_to_head"], RelationshipTransform()) 288 | O_teams <- (map["teams"], RelationshipTransform()) 289 | O_winner <- (map["winning_team_url"], RelationshipTransform()) 290 | 291 | // Implicitly Unwrapped 292 | I_players <- (map["players"], RelationshipTransform()) 293 | I_team1Lineup <- (map["team1_lineup"], RelationshipTransform()) 294 | I_team2Lineup <- (map["team1_lineup"], RelationshipTransform()) 295 | I_headToHead <- (map["head_to_head"], RelationshipTransform()) 296 | I_teams <- (map["teams"], RelationshipTransform()) 297 | I_winner <- (map["winning_team_url"], RelationshipTransform()) 298 | } 299 | } 300 | 301 | class Team: NSObject, Mappable, URIInitiable { 302 | var URI: String? 303 | var players: [Player] = [] 304 | var O_players: [Player]? 305 | var I_players: [Player]? 306 | 307 | required init(URI: String) { self.URI = URI } 308 | required init?(map: Map) {} 309 | 310 | func mapping(map: Map) { 311 | players <- (map["players"], RelationshipTransform()) 312 | O_players <- (map["players"], RelationshipTransform()) 313 | I_players <- (map["players"], RelationshipTransform()) 314 | } 315 | } 316 | 317 | class Player: Mappable, URIInitiable { 318 | required init(URI: String) {} 319 | required init?(map: Map) {} 320 | 321 | func mapping(map: Map) {} 322 | } 323 | } 324 | 325 | protocol URIInitiable { 326 | init(URI: String) 327 | } 328 | 329 | class RelationshipTransform: TransformType where ObjectType: Mappable & URIInitiable { 330 | typealias Object = ObjectType 331 | typealias JSON = [String: AnyObject] 332 | 333 | func transformFromJSON(_ value: Any?) -> Object? { 334 | guard let URI = value as? String else { return nil } 335 | let relation = ObjectType(URI: URI) 336 | 337 | return relation 338 | } 339 | 340 | func transformToJSON(_ value: Object?) -> JSON? { 341 | return nil 342 | } 343 | } 344 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/NSDecimalNumberTransformTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NestedArrayTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 10/21/15. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import XCTest 30 | import ObjectMapper 31 | 32 | class NSDecimalNumberTransformTests: XCTestCase { 33 | 34 | let mapper = Mapper() 35 | 36 | func testNSDecimalNumberTransform() { 37 | let int: Int = 11 38 | let double: Double = 11.11 39 | /* Cannot use a float literal (eg: `let decimal: Decimal = 1.66`) as this transforms the value from 1.66 to 1.6599999999999995904 */ 40 | let decimal = Decimal(string: "1.66")! 41 | let intString = "11" 42 | let doubleString = "11.11" 43 | let decimalString = "1.66" 44 | let JSONString = "{\"double\" : \(doubleString), \"int\" : \(intString), \"decimal\" : \(decimalString), \"intString\" : \"\(intString)\", \"doubleString\" : \"\(doubleString)\", \"decimalString\" : \"\(decimalString)\"}" 45 | 46 | let mappedObject = mapper.map(JSONString: JSONString) 47 | 48 | XCTAssertNotNil(mappedObject) 49 | XCTAssertEqual(mappedObject?.int, NSDecimalNumber(value: int)) 50 | XCTAssertEqual(mappedObject?.double, NSDecimalNumber(value: double)) 51 | XCTAssertEqual(mappedObject?.decimal, NSDecimalNumber(decimal: decimal)) 52 | XCTAssertEqual(mappedObject?.intString, NSDecimalNumber(string: intString)) 53 | XCTAssertEqual(mappedObject?.doubleString, NSDecimalNumber(string: doubleString)) 54 | XCTAssertEqual(mappedObject?.decimalString, NSDecimalNumber(string: decimalString)) 55 | XCTAssertEqual(mappedObject?.int?.stringValue, intString) 56 | XCTAssertEqual(mappedObject?.double?.stringValue, doubleString) 57 | XCTAssertEqual(mappedObject?.decimal?.stringValue, decimalString) 58 | } 59 | } 60 | 61 | class NSDecimalNumberType: Mappable { 62 | 63 | var int: NSDecimalNumber? 64 | var double: NSDecimalNumber? 65 | var decimal: NSDecimalNumber? 66 | var intString: NSDecimalNumber? 67 | var doubleString: NSDecimalNumber? 68 | var decimalString: NSDecimalNumber? 69 | 70 | init(){ 71 | 72 | } 73 | 74 | required init?(map: Map){ 75 | 76 | } 77 | 78 | func mapping(map: Map) { 79 | int <- (map["int"], NSDecimalNumberTransform()) 80 | double <- (map["double"], NSDecimalNumberTransform()) 81 | decimal <- (map["decimal"], NSDecimalNumberTransform()) 82 | intString <- (map["intString"], NSDecimalNumberTransform()) 83 | doubleString <- (map["doubleString"], NSDecimalNumberTransform()) 84 | decimalString <- (map["decimalString"], NSDecimalNumberTransform()) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/NestedArrayTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NestedArrayTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by Ruben Samsonyan on 10/21/15. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | import XCTest 31 | import ObjectMapper 32 | 33 | class NestedArrayTests: XCTestCase { 34 | 35 | override func setUp() { 36 | super.setUp() 37 | // Put setup code here. This method is called before the invocation of each test method in the class. 38 | } 39 | 40 | override func tearDown() { 41 | // Put teardown code here. This method is called after the invocation of each test method in the class. 42 | super.tearDown() 43 | } 44 | 45 | func testNestedArray() { 46 | let JSON: [String: Any] = [ "nested": [ ["value": 123], ["value": 456] ] ] 47 | 48 | let mapper = Mapper() 49 | 50 | let value: NestedArray! = mapper.map(JSON: JSON) 51 | XCTAssertNotNil(value) 52 | 53 | let JSONFromValue = mapper.toJSON(value) 54 | let valueFromParsedJSON: NestedArray! = mapper.map(JSON: JSONFromValue) 55 | XCTAssertNotNil(valueFromParsedJSON) 56 | 57 | XCTAssertEqual(value.value_0, valueFromParsedJSON.value_0) 58 | XCTAssertEqual(value.value_1, valueFromParsedJSON.value_1) 59 | } 60 | 61 | func testNestedObjectArray() { 62 | let value = 456 63 | let JSON: [String: Any] = [ "nested": [ ["value": 123], ["value": value] ] ] 64 | 65 | let mapper = Mapper() 66 | 67 | let mappedObject: NestedArray! = mapper.map(JSON: JSON) 68 | XCTAssertNotNil(mappedObject) 69 | 70 | XCTAssertEqual(mappedObject.nestedObject!.value, value) 71 | XCTAssertEqual(mappedObject.nestedObjectValue, value) 72 | } 73 | } 74 | 75 | class NestedArray: Mappable { 76 | 77 | var value_0: Int? 78 | var value_1: Int? 79 | 80 | var nestedObject: NestedObject? 81 | 82 | var nestedObjectValue: Int? 83 | 84 | required init?(map: Map){ 85 | 86 | } 87 | 88 | func mapping(map: Map) { 89 | value_0 <- map["nested.0.value"] 90 | value_1 <- map["nested.1.value"] 91 | 92 | nestedObject <- map["nested.1"] 93 | nestedObjectValue <- map["nested.1.value"] 94 | } 95 | } 96 | 97 | class NestedObject: Mappable { 98 | var value: Int? 99 | 100 | required init?(map: Map){} 101 | 102 | func mapping(map: Map) { 103 | value <- map["value"] 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/NullableKeysFromJSONTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NullableKeysFromJSONTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by Fabio Teles on 3/22/16. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan HImmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | import XCTest 31 | import ObjectMapper 32 | 33 | class NullableKeysFromJSONTests: XCTestCase { 34 | 35 | let fullJSONString = "{\"firstName\": \"John\", \"lastName\": \"Doe\", \"team\": \"Broncos\", \"age\": 25, \"address\": {\"street\": \"Nothing Ave\", \"number\": 101, \"city\": \"Los Angeles\"} }" 36 | let nullJSONString = "{\"firstName\": \"John\", \"lastName\": null, \"team\": \"Broncos\", \"age\": null, \"address\": {\"street\": \"Nothing Ave\", \"number\": 101, \"city\": null} }" 37 | let absentJSONString = "{\"firstName\": \"John\", \"team\": \"Broncos\", \"address\": {\"street\": \"Nothing Ave\", \"number\": 102} }" 38 | 39 | let mapper = Mapper() 40 | 41 | override func setUp() { 42 | super.setUp() 43 | // Put setup code here. This method is called before the invocation of each test method in the class. 44 | } 45 | 46 | func testMapperNullifiesValues() { 47 | guard let player = mapper.map(JSONString: fullJSONString) else { 48 | XCTFail("Mapping failed") 49 | return 50 | } 51 | 52 | XCTAssertNotNil(player.lastName) 53 | XCTAssertNotNil(player.age) 54 | XCTAssertNotNil(player.address?.city) 55 | 56 | _ = mapper.map(JSONString: nullJSONString, toObject: player) 57 | 58 | XCTAssertNotNil(player.firstName) 59 | XCTAssertNil(player.lastName) 60 | XCTAssertNil(player.age) 61 | XCTAssertNil(player.address?.city) 62 | } 63 | 64 | func testMapperAbsentValues() { 65 | guard let player = mapper.map(JSONString: fullJSONString) else { 66 | XCTFail("Mapping failed") 67 | return 68 | } 69 | 70 | XCTAssertNotNil(player.lastName) 71 | XCTAssertNotNil(player.age) 72 | XCTAssertNotNil(player.address?.city) 73 | 74 | _ = mapper.map(JSONString: absentJSONString, toObject: player) 75 | 76 | XCTAssertNotNil(player.firstName) 77 | XCTAssertNotNil(player.lastName) 78 | XCTAssertNotNil(player.age) 79 | XCTAssertNotNil(player.address?.city) 80 | XCTAssertEqual(player.address?.number, 102) 81 | } 82 | } 83 | 84 | class Player: Mappable { 85 | var firstName: String? 86 | var lastName: String? 87 | var team: String? 88 | var age: Int? 89 | var address: Address? 90 | 91 | required init?(map: Map){ 92 | mapping(map: map) 93 | } 94 | 95 | func mapping(map: Map) { 96 | firstName <- map["firstName"] 97 | lastName <- map["lastName"] 98 | team <- map["team"] 99 | age <- map["age"] 100 | address <- map["address"] 101 | } 102 | } 103 | 104 | class Address: Mappable { 105 | var street: String? 106 | var number: Int? 107 | var city: String? 108 | 109 | required init?(map: Map){ 110 | mapping(map: map) 111 | } 112 | 113 | func mapping(map: Map) { 114 | street <- map["street"] 115 | number <- map["number"] 116 | city <- map["city"] 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/PerformanceTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PerformanceTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2015-09-21. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | import XCTest 31 | import ObjectMapper 32 | 33 | class PerformanceTests: XCTestCase { 34 | 35 | let JSONTestString: String = { 36 | let subObjectJSON = "{\"string\":\"This is a string\", \"int\": 12,\"double\":12.27,\"float\":12.3212, \"bool\":false, \"arr\":[ \"bla\", true, 42 ], \"dict\":{ \"key1\" : \"value1\", \"key2\" : false, \"key3\" : 142 } }" 37 | 38 | let objectJSONString = "{\"string\":\"This is a string\", \"int\": 12,\"double\":12.27,\"float\":12.3212, \"bool\":false, \"arr\":[ \"bla\", true, 42 ], \"dict\":{ \"key1\" : \"value1\", \"key2\" : false, \"key3\" : 142 }, \"object\": \(subObjectJSON), \"objects\":{ \"key1\": \(subObjectJSON), \"key2\": \(subObjectJSON)}}" 39 | 40 | var JSONString = "[" 41 | for _ in 0...1000 { 42 | JSONString += "\(objectJSONString)," 43 | } 44 | JSONString += "\(objectJSONString)]" 45 | return JSONString 46 | }() 47 | 48 | override func setUp() { 49 | super.setUp() 50 | // Put setup code here. This method is called before the invocation of each test method in the class. 51 | } 52 | 53 | override func tearDown() { 54 | // Put teardown code here. This method is called after the invocation of each test method in the class. 55 | super.tearDown() 56 | } 57 | 58 | func testPerformance() { 59 | self.measure { 60 | // Put the code you want to measure the time of here. 61 | _ = Mapper().mapArray(JSONString: self.JSONTestString) 62 | } 63 | } 64 | 65 | func testPerformanceCluster() { 66 | self.measure { 67 | // Put the code you want to measure the time of here. 68 | _ = Mapper().mapArray(JSONString: self.JSONTestString) 69 | } 70 | } 71 | 72 | func testPerformanceImmutable() { 73 | self.measure { 74 | _ = try? Mapper().mapArray(JSONString: self.JSONTestString) 75 | } 76 | } 77 | } 78 | 79 | class PerformanceMappableObject: Mappable { 80 | 81 | var string: String? 82 | var int: Int? 83 | var double: Double? 84 | var float: Float? 85 | var bool: Bool? 86 | var array: [Any]? 87 | var dictionary: [String: Any]? 88 | var object: PerformanceMappableObject? 89 | var objects: [PerformanceMappableObject]? 90 | 91 | required init?(map: Map){ 92 | 93 | } 94 | 95 | func mapping(map: Map) { 96 | string <- map["string"] 97 | int <- map["int"] 98 | double <- map["double"] 99 | float <- map["float"] 100 | bool <- map["bool"] 101 | array <- map["array"] 102 | dictionary <- map["dictionary"] 103 | object <- map["object"] 104 | objects <- map["objects"] 105 | } 106 | } 107 | 108 | class PerformanceStaticMappableObject: StaticMappable { 109 | 110 | var string: String? 111 | var int: Int? 112 | var double: Double? 113 | var float: Float? 114 | var bool: Bool? 115 | var array: [Any]? 116 | var dictionary: [String: Any]? 117 | var object: PerformanceStaticMappableObject? 118 | var objects: [PerformanceStaticMappableObject]? 119 | 120 | static func objectForMapping(map: Map) -> BaseMappable? { 121 | return PerformanceStaticMappableObject() 122 | } 123 | 124 | func mapping(map: Map) { 125 | string <- map["string"] 126 | int <- map["int"] 127 | double <- map["double"] 128 | float <- map["float"] 129 | bool <- map["bool"] 130 | array <- map["array"] 131 | dictionary <- map["dictionary"] 132 | object <- map["object"] 133 | objects <- map["objects"] 134 | } 135 | } 136 | 137 | class PerformanceImmutableMappableObject: ImmutableMappable { 138 | 139 | let string: String? 140 | let int: Int? 141 | let double: Double? 142 | let float: Float? 143 | let bool: Bool? 144 | let array: [Any]? 145 | let dictionary: [String: Any]? 146 | let object: PerformanceImmutableMappableObject? 147 | let objects: [PerformanceImmutableMappableObject]? 148 | 149 | required init(map: Map) throws { 150 | string = try map.value("string") 151 | int = try map.value("int") 152 | double = try map.value("double") 153 | float = try map.value("float") 154 | bool = try map.value("bool") 155 | array = try map.value("array") 156 | dictionary = try map.value("dictionary") 157 | object = try map.value("object") 158 | objects = try map.value("objects") 159 | } 160 | 161 | func mapping(map: Map) { 162 | string >>> map["string"] 163 | int >>> map["int"] 164 | double >>> map["double"] 165 | float >>> map["float"] 166 | bool >>> map["bool"] 167 | array >>> map["array"] 168 | dictionary >>> map["dictionary"] 169 | object >>> map["object"] 170 | objects >>> map["objects"] 171 | } 172 | } 173 | 174 | 175 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/ToObjectTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReferenceTypesFromJSON.swift 3 | // ObjectMapper 4 | // 5 | // Created by Tristan Himmelman on 2015-11-29. 6 | // 7 | // The MIT License (MIT) 8 | // 9 | // Copyright (c) 2014-2018 Tristan Himmelman 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | import Foundation 30 | import XCTest 31 | import ObjectMapper 32 | 33 | class ToObjectTests: XCTestCase { 34 | 35 | override func setUp() { 36 | super.setUp() 37 | // Put setup code here. This method is called before the invocation of each test method in the class. 38 | } 39 | 40 | override func tearDown() { 41 | // Put teardown code here. This method is called after the invocation of each test method in the class. 42 | super.tearDown() 43 | } 44 | 45 | func testMappingPersonFromJSON(){ 46 | let name = "ASDF" 47 | let spouseName = "HJKL" 48 | let JSONString = "{\"name\" : \"\(name)\", \"spouse\" : {\"name\" : \"\(spouseName)\"}}" 49 | 50 | let mappedObject = Mapper().map(JSONString: JSONString) 51 | 52 | XCTAssertNotNil(mappedObject) 53 | XCTAssertEqual(mappedObject?.name, name) 54 | XCTAssertEqual(mappedObject?.spouse?.name, spouseName) 55 | } 56 | 57 | func testUpdatingChildObject(){ 58 | let name = "ASDF" 59 | let initialSpouseName = "HJKL" 60 | let updatedSpouseName = "QWERTY" 61 | let initialJSONString = "{\"name\" : \"\(name)\", \"spouse\" : {\"name\" : \"\(initialSpouseName)\"}}" 62 | let updatedJSONString = "{\"name\" : \"\(name)\", \"spouse\" : {\"name\" : \"\(updatedSpouseName)\"}}" 63 | 64 | let mappedObject = Mapper().map(JSONString: initialJSONString) 65 | let initialSpouse = mappedObject?.spouse 66 | 67 | XCTAssertNotNil(mappedObject) 68 | 69 | let updatedObject = Mapper().map(JSONString: updatedJSONString, toObject: mappedObject!) 70 | 71 | XCTAssert(initialSpouse === updatedObject.spouse, "Expected mapping to update the existing object not create a new one") 72 | XCTAssertEqual(updatedObject.spouse?.name, updatedSpouseName) 73 | XCTAssertEqual(initialSpouse?.name, updatedSpouseName) 74 | } 75 | 76 | func testUpdatingChildDictionary(){ 77 | let childKey = "child_1" 78 | let initialChildName = "HJKL" 79 | let updatedChildName = "QWERTY" 80 | let initialJSONString = "{\"children\" : {\"\(childKey)\" : {\"name\" : \"\(initialChildName)\"}}}" 81 | let updatedJSONString = "{\"children\" : {\"\(childKey)\" : {\"name\" : \"\(updatedChildName)\"}}}" 82 | 83 | let mappedObject = Mapper().map(JSONString: initialJSONString) 84 | let initialChild = mappedObject?.children?[childKey] 85 | 86 | XCTAssertNotNil(mappedObject) 87 | XCTAssertNotNil(initialChild) 88 | XCTAssertEqual(initialChild?.name, initialChildName) 89 | 90 | _ = Mapper().map(JSONString: updatedJSONString, toObject: mappedObject!) 91 | 92 | let updatedChild = mappedObject?.children?[childKey] 93 | XCTAssert(initialChild === updatedChild, "Expected mapping to update the existing object not create a new one") 94 | XCTAssertEqual(updatedChild?.name, updatedChildName) 95 | XCTAssertEqual(initialChild?.name, updatedChildName) 96 | } 97 | 98 | func testToObjectFromString() { 99 | let username = "bob" 100 | let JSONString = "{\"username\":\"\(username)\"}" 101 | 102 | let user = User() 103 | user.username = "Tristan" 104 | 105 | _ = Mapper().map(JSONString: JSONString, toObject: user) 106 | 107 | XCTAssertEqual(user.username, username) 108 | } 109 | 110 | func testToObjectFromJSON() { 111 | let username = "bob" 112 | let JSON = ["username": username] 113 | 114 | let user = User() 115 | user.username = "Tristan" 116 | 117 | _ = Mapper().map(JSON: JSON, toObject: user) 118 | 119 | XCTAssertEqual(username, user.username) 120 | } 121 | 122 | func testToObjectFromAny() { 123 | let username = "bob" 124 | let userJSON = ["username": username] 125 | 126 | let user = User() 127 | user.username = "Tristan" 128 | 129 | _ = Mapper().map(JSONObject: userJSON as Any, toObject: user) 130 | 131 | XCTAssertEqual(user.username, username) 132 | } 133 | 134 | class Person: Mappable { 135 | var name: String? 136 | var spouse: Person? 137 | var children: [String: Person]? 138 | 139 | required init?(map: Map) { 140 | 141 | } 142 | 143 | func mapping(map: Map) { 144 | name <- map["name"] 145 | spouse <- map["spouse"] 146 | children <- map["children"] 147 | } 148 | } 149 | 150 | class User: Mappable { 151 | 152 | var username: String = "" 153 | 154 | init(){ 155 | 156 | } 157 | 158 | required init?(map: Map){ 159 | 160 | } 161 | 162 | func mapping(map: Map) { 163 | username <- map["username"] 164 | } 165 | } 166 | 167 | struct HumanInfo: Mappable { 168 | var name: String? 169 | 170 | init(name: String) { 171 | self.name = name 172 | } 173 | 174 | init?(map: Map) { 175 | 176 | } 177 | 178 | mutating func mapping(map: Map) { 179 | name <- map["name"] 180 | } 181 | } 182 | 183 | struct Human: Mappable { 184 | var info: HumanInfo? 185 | 186 | init(name: String) { 187 | info = HumanInfo(name: name) 188 | } 189 | 190 | init?(map: Map) { 191 | 192 | } 193 | 194 | mutating func mapping(map: Map) { 195 | info <- map["info"] 196 | } 197 | } 198 | 199 | func testConsume() { 200 | var human1 = Human(name: "QW") //has a with name "QW" 201 | let human2 = Human(name: "ER") //has a with name "ER" 202 | human1 = Mapper().map(JSON: human2.toJSON(), toObject: human1) 203 | 204 | XCTAssertEqual(human1.info?.name, human2.info?.name) 205 | } 206 | } 207 | 208 | -------------------------------------------------------------------------------- /Tests/ObjectMapperTests/URLTransformTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLTransformTests.swift 3 | // ObjectMapper 4 | // 5 | // Created by pawel-rusin on 4/7/17. 6 | // 7 | // Copyright (c) 2014-2018 Tristan Himmelman 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | import XCTest 28 | import ObjectMapper 29 | 30 | class URLTransformTests: XCTestCase { 31 | 32 | func testUrlQueryAllowed() { 33 | let urlTransform = URLTransform() 34 | let input = "https://example.com/search?query=foo" 35 | let output = urlTransform.transformFromJSON(input) 36 | 37 | XCTAssertEqual(output, URL(string: "https://example.com/search?query=foo")) 38 | } 39 | 40 | func testCanPassInAllowedCharacterSet() { 41 | var characterSet = CharacterSet.urlQueryAllowed 42 | characterSet.insert(charactersIn: "%") 43 | let urlTransform = URLTransform(allowedCharacterSet: characterSet) 44 | let input = "https://example.com/%25" 45 | let output = urlTransform.transformFromJSON(input) 46 | 47 | XCTAssertEqual(output, URL(string: "https://example.com/%25")) 48 | } 49 | } 50 | --------------------------------------------------------------------------------