diff --git a/ObjectMapper.xcodeproj/project.pbxproj b/ObjectMapper.xcodeproj/project.pbxproj
index 329a283b..8e6e8c6d 100644
--- a/ObjectMapper.xcodeproj/project.pbxproj
+++ b/ObjectMapper.xcodeproj/project.pbxproj
@@ -728,11 +728,11 @@
};
6AAC8F7519F03C2900E7A677 = {
CreatedOnToolsVersion = 6.0.1;
- LastSwiftMigration = 1120;
+ LastSwiftMigration = 0900;
};
6AAC8F8019F03C2900E7A677 = {
CreatedOnToolsVersion = 6.0.1;
- LastSwiftMigration = 1120;
+ LastSwiftMigration = 0900;
};
CD1602FE1AC023D5000CD69A = {
CreatedOnToolsVersion = 6.2;
@@ -1108,7 +1108,7 @@
PRODUCT_NAME = "$(PROJECT_NAME)";
SDKROOT = appletvos;
SKIP_INSTALL = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 9.0;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
@@ -1137,7 +1137,7 @@
PRODUCT_NAME = "$(PROJECT_NAME)";
SDKROOT = appletvos;
SKIP_INSTALL = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 9.0;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
@@ -1156,7 +1156,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.tristanhimmelman.ObjectMapper-tvOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = appletvos;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 4.2;
TVOS_DEPLOYMENT_TARGET = 9.0;
};
name = Debug;
@@ -1174,7 +1174,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.tristanhimmelman.ObjectMapper-tvOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = appletvos;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 4.2;
TVOS_DEPLOYMENT_TARGET = 9.0;
};
name = Release;
@@ -1200,7 +1200,7 @@
PRODUCT_NAME = "$(PROJECT_NAME)";
SDKROOT = watchos;
SKIP_INSTALL = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = 4;
TVOS_DEPLOYMENT_TARGET = 9.0;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
@@ -1228,7 +1228,7 @@
PRODUCT_NAME = "$(PROJECT_NAME)";
SDKROOT = watchos;
SKIP_INSTALL = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = 4;
TVOS_DEPLOYMENT_TARGET = 9.0;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
@@ -1363,7 +1363,8 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.tristanhimmelman.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(PROJECT_NAME)";
SKIP_INSTALL = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_SWIFT3_OBJC_INFERENCE = Default;
+ SWIFT_VERSION = 4.2;
TVOS_DEPLOYMENT_TARGET = 9.0;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
};
@@ -1384,7 +1385,8 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.tristanhimmelman.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(PROJECT_NAME)";
SKIP_INSTALL = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_SWIFT3_OBJC_INFERENCE = Default;
+ SWIFT_VERSION = 4.2;
TVOS_DEPLOYMENT_TARGET = 9.0;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
};
@@ -1402,7 +1404,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.heart.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 5.0;
+ SWIFT_SWIFT3_OBJC_INFERENCE = Default;
+ SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -1414,7 +1417,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.heart.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 5.0;
+ SWIFT_SWIFT3_OBJC_INFERENCE = Default;
+ SWIFT_VERSION = 4.0;
};
name = Release;
};
@@ -1442,7 +1446,7 @@
PRODUCT_NAME = "$(PROJECT_NAME)";
SDKROOT = macosx;
SKIP_INSTALL = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 4.2;
TVOS_DEPLOYMENT_TARGET = 9.0;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
};
@@ -1470,7 +1474,7 @@
PRODUCT_NAME = "$(PROJECT_NAME)";
SDKROOT = macosx;
SKIP_INSTALL = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 4.2;
TVOS_DEPLOYMENT_TARGET = 9.0;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
};
@@ -1491,7 +1495,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.heart.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 4.2;
};
name = Debug;
};
@@ -1508,7 +1512,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.heart.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 4.2;
};
name = Release;
};
@@ -1532,7 +1536,7 @@
PRODUCT_NAME = ObjectMapper;
SDKROOT = macosx;
SKIP_INSTALL = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 4.2;
};
name = Debug;
};
@@ -1557,7 +1561,7 @@
PRODUCT_NAME = ObjectMapper;
SDKROOT = macosx;
SKIP_INSTALL = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 4.2;
};
name = Release;
};
diff --git a/ObjectMapper.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ObjectMapper.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000..18d98100
--- /dev/null
+++ b/ObjectMapper.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/README.md b/README.md
index 63c15abf..bceae5b3 100644
--- a/README.md
+++ b/README.md
@@ -248,6 +248,7 @@ init(map: Map) throws {
createdAt = try map.value("createdAt", using: DateTransform()) // throws an error when it fails
updatedAt = try? map.value("updatedAt", using: DateTransform()) // optional
posts = (try? map.value("posts")) ?? [] // optional + default value
+ surname = try? map.value("surname", default: "DefaultSurname") // optional + default value as an argument
}
```
diff --git a/Sources/Map.swift b/Sources/Map.swift
index 38dc2a3f..1ca9903a 100644
--- a/Sources/Map.swift
+++ b/Sources/Map.swift
@@ -202,3 +202,45 @@ private func valueFor(_ keyPathComponents: ArraySlice, array: [Any]) ->
return (false, nil)
}
+
+// MARK: - Default Value
+
+public extension Map {
+
+ /// Returns `default` value if there is nothing to parse.
+ func value(_ key: String, default: T.Object, using transform: T) throws -> T.Object where T: TransformType {
+ if let value: T.Object = try? self.value(key, using: transform) {
+ return value
+ } else {
+ return `default`
+ }
+ }
+
+ /// Returns `default` value if there is nothing to parse.
+ func value(_ key: String, default: T) throws -> T {
+ if let value: T = try? self.value(key) {
+ return value
+ } else {
+ return `default`
+ }
+ }
+
+ /// Returns `default` value if there is nothing to parse.
+ func value(_ key: String, default: [T]) -> [T] {
+ do {
+ let value: [T] = try self.value(key)
+ return value
+ } catch {
+ return `default`
+ }
+ }
+
+ /// Returns `default` value if there is nothing to parse.
+ func value(_ key: String, default: T) throws -> T where T: BaseMappable {
+ if let value: T = try? self.value(key) as T {
+ return value
+ } else {
+ return `default`
+ }
+ }
+}
diff --git a/Tests/ObjectMapperTests/ImmutableTests.swift b/Tests/ObjectMapperTests/ImmutableTests.swift
index f722add1..bafba916 100644
--- a/Tests/ObjectMapperTests/ImmutableTests.swift
+++ b/Tests/ObjectMapperTests/ImmutableTests.swift
@@ -201,12 +201,12 @@ class ImmutableObjectTests: XCTestCase {
XCTAssertEqual(immutable.delimiterNestedDictionary, ["a": 10, "b": 20, "c": 30])
let JSON2: [String: Any] = [ "prop1": "prop1", "prop2": NSNull() ]
- let immutable2 = try? mapper.map(JSON: JSON2) as Struct
+ let immutable2 = try? mapper.map(JSON: JSON2)
XCTAssertNil(immutable2)
// TODO: ImmutableMappable to JSON
let JSONFromObject = mapper.toJSON(immutable)
- let objectFromJSON = try? mapper.map(JSON: JSONFromObject) as Struct
+ let objectFromJSON = try? mapper.map(JSON: JSONFromObject)
XCTAssertNotNil(objectFromJSON)
assertImmutableObjectsEqual(objectFromJSON!, immutable)
}
diff --git a/Tests/ObjectMapperTests/MapContextTests.swift b/Tests/ObjectMapperTests/MapContextTests.swift
index 3bf4e250..13a4b34f 100644
--- a/Tests/ObjectMapperTests/MapContextTests.swift
+++ b/Tests/ObjectMapperTests/MapContextTests.swift
@@ -138,7 +138,7 @@ class MapContextTests: XCTestCase {
let JSON = ["name": "Anton"]
let context = ImmutableContext(isDeveloper: true)
- let person = try? Mapper(context: context).map(JSON: JSON) as ImmutablePerson
+ let person = try? Mapper(context: context).map(JSON: JSON)
XCTAssertNotNil(person)
@@ -149,7 +149,7 @@ class MapContextTests: XCTestCase {
let JSON = ["name": "Anton"]
let context = ImmutableContext(isDeveloper: true)
- let person = try? ImmutablePerson(JSON: JSON, context: context) as ImmutablePerson
+ let person = try? ImmutablePerson(JSON: JSON, context: context)
XCTAssertNotNil(person)
XCTAssertEqual(person?.isDeveloper ?? !context.isDeveloper, context.isDeveloper)
@@ -172,7 +172,7 @@ class MapContextTests: XCTestCase {
let JSON = ["person": ["name": "Anton"]]
let context = ImmutableContext(isDeveloper: true)
- let nestedPerson = try? Mapper(context: context).map(JSON: JSON) as ImmutableNestedPerson
+ let nestedPerson = try? Mapper(context: context).map(JSON: JSON)
XCTAssertNotNil(nestedPerson)
XCTAssertEqual(nestedPerson?.person.isDeveloper ?? !context.isDeveloper, context.isDeveloper)
@@ -182,7 +182,7 @@ class MapContextTests: XCTestCase {
let JSON = ["person": ["name": "Anton"]]
let context = ImmutableContext(isDeveloper: true)
- let nestedPerson = try? ImmutableNestedPerson(JSON: JSON, context: context) as ImmutableNestedPerson
+ let nestedPerson = try? ImmutableNestedPerson(JSON: JSON, context: context)
XCTAssertNotNil(nestedPerson)
XCTAssertEqual(nestedPerson?.person.isDeveloper ?? !context.isDeveloper, context.isDeveloper)
@@ -207,7 +207,7 @@ class MapContextTests: XCTestCase {
let JSON = ["persons": [["name": "Tristan"], ["name": "Anton"]]]
let context = ImmutableContext(isDeveloper: true)
- let personList = try? Mapper(context: context).map(JSON: JSON) as ImmutablePersonList
+ let personList = try? Mapper(context: context).map(JSON: JSON)
XCTAssertNotNil(personList)
@@ -220,7 +220,7 @@ class MapContextTests: XCTestCase {
let JSON = ["persons": [["name": "Tristan"], ["name": "Anton"]]]
let context = ImmutableContext(isDeveloper: true)
- let personList = try? ImmutablePersonList(JSON: JSON, context: context) as ImmutablePersonList
+ let personList = try? ImmutablePersonList(JSON: JSON, context: context)
XCTAssertNotNil(personList)
@@ -242,6 +242,32 @@ class MapContextTests: XCTestCase {
XCTFail()
}
+
+ func testDefaultArgumentWithoutValue() {
+ let JSON: [String: Any] = [:]
+ let dog = try? Mapper().map(JSON: JSON) as ImmutableDog
+
+ XCTAssertNotNil(dog)
+ XCTAssertTrue(dog!.name == "Sasha")
+ }
+
+ func testDefaultArgumentWithValue() {
+ let JSON = ["name": "Sofie"]
+ let dog = try? Mapper().map(JSON: JSON) as ImmutableDog
+
+ XCTAssertNotNil(dog)
+ XCTAssertTrue(dog!.name == "Sofie")
+ }
+
+ // MARK: - Default Argument
+ public struct ImmutableDog: ImmutableMappable {
+ public let name: String
+
+ /// Define `default` value to use if it is nothing to parse in `name`
+ public init(map: Map) throws {
+ name = try map.value("name", default: "Sasha")
+ }
+ }
// MARK: - Nested Types
// MARK: BaseMappable
diff --git a/Tests/ObjectMapperTests/MappableExtensionsTests.swift b/Tests/ObjectMapperTests/MappableExtensionsTests.swift
index d3ee7960..b885cf1f 100644
--- a/Tests/ObjectMapperTests/MappableExtensionsTests.swift
+++ b/Tests/ObjectMapperTests/MappableExtensionsTests.swift
@@ -44,14 +44,12 @@ struct TestMappable: Mappable, Equatable, Hashable {
mutating func mapping(map: Map) {
value <- map["value"]
}
-
-
- func hash(into hasher: inout Hasher) {
+
+ var hashValue: Int {
if let value = value {
- hasher.combine(value)
- } else {
- hasher.combine(NSIntegerMax)
+ return value.hashValue
}
+ return NSIntegerMax
}
}
diff --git a/Tests/ObjectMapperTests/PerformanceTests.swift b/Tests/ObjectMapperTests/PerformanceTests.swift
index fa2819be..6e0620ba 100644
--- a/Tests/ObjectMapperTests/PerformanceTests.swift
+++ b/Tests/ObjectMapperTests/PerformanceTests.swift
@@ -71,7 +71,7 @@ class PerformanceTests: XCTestCase {
func testPerformanceImmutable() {
self.measure {
- _ = try? Mapper().mapArray(JSONString: self.JSONTestString) as [PerformanceImmutableMappableObject]
+ _ = try? Mapper().mapArray(JSONString: self.JSONTestString)
}
}
}