Skip to content

Commit

Permalink
Merge pull request #1085 from emrcftci/feature/defaultValue
Browse files Browse the repository at this point in the history
Add `default` argument to Map's value(_)
  • Loading branch information
tristanhimmelman committed May 17, 2020
2 parents 88465f8 + 880ea1f commit 72427ba
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 33 deletions.
40 changes: 22 additions & 18 deletions ObjectMapper.xcodeproj/project.pbxproj
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
};
Expand All @@ -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;
};
Expand All @@ -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;
};
Expand All @@ -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;
};
Expand Down Expand Up @@ -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;
};
Expand Down Expand Up @@ -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;
};
Expand All @@ -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;
};
Expand All @@ -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;
};
Expand All @@ -1532,7 +1536,7 @@
PRODUCT_NAME = ObjectMapper;
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 4.2;
};
name = Debug;
};
Expand All @@ -1557,7 +1561,7 @@
PRODUCT_NAME = ObjectMapper;
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 4.2;
};
name = Release;
};
Expand Down
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -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
}
```

Expand Down
42 changes: 42 additions & 0 deletions Sources/Map.swift
Expand Up @@ -202,3 +202,45 @@ private func valueFor(_ keyPathComponents: ArraySlice<String>, array: [Any]) ->

return (false, nil)
}

// MARK: - Default Value

public extension Map {

/// Returns `default` value if there is nothing to parse.
func value<T>(_ 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<T>(_ 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<T: BaseMappable>(_ 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<T>(_ key: String, default: T) throws -> T where T: BaseMappable {
if let value: T = try? self.value(key) as T {
return value
} else {
return `default`
}
}
}
4 changes: 2 additions & 2 deletions Tests/ObjectMapperTests/ImmutableTests.swift
Expand Up @@ -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)
}
Expand Down
38 changes: 32 additions & 6 deletions Tests/ObjectMapperTests/MapContextTests.swift
Expand Up @@ -138,7 +138,7 @@ class MapContextTests: XCTestCase {
let JSON = ["name": "Anton"]
let context = ImmutableContext(isDeveloper: true)

let person = try? Mapper<ImmutablePerson>(context: context).map(JSON: JSON) as ImmutablePerson
let person = try? Mapper<ImmutablePerson>(context: context).map(JSON: JSON)

XCTAssertNotNil(person)

Expand All @@ -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)
Expand All @@ -172,7 +172,7 @@ class MapContextTests: XCTestCase {
let JSON = ["person": ["name": "Anton"]]
let context = ImmutableContext(isDeveloper: true)

let nestedPerson = try? Mapper<ImmutableNestedPerson>(context: context).map(JSON: JSON) as ImmutableNestedPerson
let nestedPerson = try? Mapper<ImmutableNestedPerson>(context: context).map(JSON: JSON)

XCTAssertNotNil(nestedPerson)
XCTAssertEqual(nestedPerson?.person.isDeveloper ?? !context.isDeveloper, context.isDeveloper)
Expand All @@ -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)
Expand All @@ -207,7 +207,7 @@ class MapContextTests: XCTestCase {
let JSON = ["persons": [["name": "Tristan"], ["name": "Anton"]]]
let context = ImmutableContext(isDeveloper: true)

let personList = try? Mapper<ImmutablePersonList>(context: context).map(JSON: JSON) as ImmutablePersonList
let personList = try? Mapper<ImmutablePersonList>(context: context).map(JSON: JSON)

XCTAssertNotNil(personList)

Expand All @@ -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)

Expand All @@ -242,6 +242,32 @@ class MapContextTests: XCTestCase {

XCTFail()
}

func testDefaultArgumentWithoutValue() {
let JSON: [String: Any] = [:]
let dog = try? Mapper<ImmutableDog>().map(JSON: JSON) as ImmutableDog

XCTAssertNotNil(dog)
XCTAssertTrue(dog!.name == "Sasha")
}

func testDefaultArgumentWithValue() {
let JSON = ["name": "Sofie"]
let dog = try? Mapper<ImmutableDog>().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
Expand Down
10 changes: 4 additions & 6 deletions Tests/ObjectMapperTests/MappableExtensionsTests.swift
Expand Up @@ -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
}
}

Expand Down
2 changes: 1 addition & 1 deletion Tests/ObjectMapperTests/PerformanceTests.swift
Expand Up @@ -71,7 +71,7 @@ class PerformanceTests: XCTestCase {

func testPerformanceImmutable() {
self.measure {
_ = try? Mapper<PerformanceImmutableMappableObject>().mapArray(JSONString: self.JSONTestString) as [PerformanceImmutableMappableObject]
_ = try? Mapper<PerformanceImmutableMappableObject>().mapArray(JSONString: self.JSONTestString)
}
}
}
Expand Down

0 comments on commit 72427ba

Please sign in to comment.