Skip to content

Commit 41d5879

Browse files
committed
Change the return type of map(JSON:) to optional, not IUO, for better type safety
`mapArray()` and `mapDictionary()` now filter out nil values from their entires.
1 parent 990bf7d commit 41d5879

File tree

5 files changed

+44
-30
lines changed

5 files changed

+44
-30
lines changed

ObjectMapper/Core/Mapper.swift

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ public final class Mapper<N: Mappable> {
150150
/**
151151
* Maps a JSON dictionary to an object that conforms to Mappable
152152
*/
153-
public func map(JSON: [String : AnyObject]) -> N! {
153+
public func map(JSON: [String : AnyObject]) -> N? {
154154
let map = Map(mappingType: .fromJSON, JSONDictionary: JSON)
155155
let object = N(map)
156156
return object
@@ -191,10 +191,13 @@ public final class Mapper<N: Mappable> {
191191
/**
192192
* Maps an array of JSON dictionary to an array of object that conforms to Mappable
193193
*/
194-
public func mapArray(JSON: [[String : AnyObject]]) -> [N] {
195-
return JSON.map {
194+
public func mapArray(JSONArray: [[String : AnyObject]]) -> [N] {
195+
return JSONArray.reduce([]) { (var values, JSON) in
196196
// map every element in JSON array to type N
197-
return self.map($0)
197+
if let value = self.map(JSON) {
198+
values.append(value)
199+
}
200+
return values
198201
}
199202
}
200203

@@ -213,9 +216,14 @@ public final class Mapper<N: Mappable> {
213216
* Maps a JSON dictionary of dictionaries to a dictionary of objects that conform to Mappable.
214217
*/
215218
public func mapDictionary(JSON: [String : [String : AnyObject]]) -> [String : N] {
216-
return JSON.map { key, value in
219+
return reduce(JSON, [String: N]()) { (var values, element) in
220+
let (key, value) = element
221+
217222
// map every value in dictionary to type N
218-
return (key, self.map(value))
223+
if let newValue = self.map(value) {
224+
values[key] = newValue
225+
}
226+
return values
219227
}
220228
}
221229

ObjectMapperTests/BasicTypesTestsFromJSON.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,8 @@ class BasicTypesTestsFromJSON: XCTestCase {
253253
let json: [String: [String: AnyObject]] = ["dictStringString":["string": "string"], "dictStringBool":["string": false], "dictStringInt":["string": 1], "dictStringDouble":["string": 1.1], "dictStringFloat":["string": 1.2]]
254254

255255
let mapper = Mapper<TestCollectionOfPrimitives>()
256-
let testSet = mapper.map(json)
256+
let testSet: TestCollectionOfPrimitives! = mapper.map(json)
257+
expect(testSet).notTo(beNil())
257258

258259
expect(testSet.dictStringString).notTo(beEmpty())
259260
expect(testSet.dictStringInt).notTo(beEmpty())

ObjectMapperTests/CustomTransformTests.swift

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ class CustomTransformTests: XCTestCase {
3333
let JSON = mapper.toJSON(transforms)
3434
let parsedTransforms = mapper.map(JSON)
3535
expect(parsedTransforms).notTo(beNil())
36-
expect(parsedTransforms.date).to(equal(transforms.date))
37-
expect(parsedTransforms.dateOpt).to(equal(transforms.dateOpt))
36+
expect(parsedTransforms?.date).to(equal(transforms.date))
37+
expect(parsedTransforms?.dateOpt).to(equal(transforms.dateOpt))
3838
}
3939

4040
func testISO8601DateTransform() {
@@ -45,27 +45,28 @@ class CustomTransformTests: XCTestCase {
4545

4646
let parsedTransforms = mapper.map(JSON)
4747
expect(parsedTransforms).notTo(beNil())
48-
expect(parsedTransforms.ISO8601Date).to(equal(transforms.ISO8601Date))
49-
expect(parsedTransforms.ISO8601DateOpt).to(equal(transforms.ISO8601DateOpt))
48+
expect(parsedTransforms?.ISO8601Date).to(equal(transforms.ISO8601Date))
49+
expect(parsedTransforms?.ISO8601DateOpt).to(equal(transforms.ISO8601DateOpt))
5050
}
5151

5252
func testISO8601DateTransformWithInvalidInput() {
5353
var JSON: [String: AnyObject] = ["ISO8601Date": ""]
5454
let transforms = mapper.map(JSON)
5555

56-
expect(transforms.ISO8601DateOpt).to(beNil())
56+
expect(transforms?.ISO8601DateOpt).to(beNil())
5757

5858
JSON["ISO8601Date"] = "incorrect format"
5959

6060
let transforms2 = mapper.map(JSON)
6161

62-
expect(transforms2.ISO8601DateOpt).to(beNil())
62+
expect(transforms2?.ISO8601DateOpt).to(beNil())
6363
}
6464

6565
func testCustomFormatDateTransform(){
6666
let dateString = "2015-03-03T02:36:44"
6767
var JSON: [String: AnyObject] = ["customFormateDate": dateString]
68-
let transform = mapper.map(JSON)
68+
let transform: Transforms! = mapper.map(JSON)
69+
expect(transform).notTo(beNil())
6970

7071
let JSONOutput = mapper.toJSON(transform)
7172

@@ -77,7 +78,7 @@ class CustomTransformTests: XCTestCase {
7778
var JSON: [String: AnyObject] = ["intWithString": "\(intValue)"]
7879
let transforms = mapper.map(JSON)
7980

80-
expect(transforms.intWithString).to(equal(intValue))
81+
expect(transforms?.intWithString).to(equal(intValue))
8182
}
8283

8384
func testInt64MaxValue() {
@@ -88,7 +89,7 @@ class CustomTransformTests: XCTestCase {
8889

8990
let parsedTransforms = mapper.map(JSON)
9091
expect(parsedTransforms).notTo(beNil())
91-
expect(parsedTransforms.int64Value).to(equal(transforms.int64Value))
92+
expect(parsedTransforms?.int64Value).to(equal(transforms.int64Value))
9293
}
9394

9495
func testURLTranform() {
@@ -100,17 +101,17 @@ class CustomTransformTests: XCTestCase {
100101

101102
let parsedTransforms = mapper.map(JSON)
102103
expect(parsedTransforms).notTo(beNil())
103-
expect(parsedTransforms.URL).to(equal(transforms.URL))
104-
expect(parsedTransforms.URLOpt).to(equal(transforms.URLOpt))
104+
expect(parsedTransforms?.URL).to(equal(transforms.URL))
105+
expect(parsedTransforms?.URLOpt).to(equal(transforms.URLOpt))
105106
}
106107

107108
func testEnumTransform() {
108109
var JSON: [String: AnyObject] = ["firstImageType" : "cover", "secondImageType" : "thumbnail"]
109110
let transforms = mapper.map(JSON)
110111

111112
let imageType = Transforms.ImageType.self
112-
expect(transforms.firstImageType).to(equal(imageType.Cover))
113-
expect(transforms.secondImageType).to(equal(imageType.Thumbnail))
113+
expect(transforms?.firstImageType).to(equal(imageType.Cover))
114+
expect(transforms?.secondImageType).to(equal(imageType.Thumbnail))
114115
}
115116
}
116117

ObjectMapperTests/NestedKeysTests.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,12 @@ class NestedKeysTests: XCTestCase {
5959

6060
let mapper = Mapper<NestedKeys>()
6161

62-
let value = mapper.map(JSON)
62+
let value: NestedKeys! = mapper.map(JSON)
63+
expect(value).notTo(beNil())
64+
6365
let JSONFromValue = mapper.toJSON(value)
64-
let valueFromParsedJSON = mapper.map(JSONFromValue)
66+
let valueFromParsedJSON: NestedKeys! = mapper.map(JSONFromValue)
67+
expect(valueFromParsedJSON).notTo(beNil())
6568

6669
expect(value.int64).to(equal(valueFromParsedJSON.int64))
6770
expect(value.bool).to(equal(valueFromParsedJSON.bool))

ObjectMapperTests/ObjectMapperTests.swift

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ class ObjectMapperTests: XCTestCase {
2929
let mapper = Mapper<Immutable>()
3030
let JSON = [ "prop1": "Immutable!", "prop2": 255, "prop3": true ]
3131

32-
let immutable = mapper.map(JSON)
33-
expect(immutable.prop1).to(equal("Immutable!"))
34-
expect(immutable.prop2).to(equal(255))
35-
expect(immutable.prop3).to(equal(true))
32+
let immutable: Immutable! = mapper.map(JSON)
33+
expect(immutable).notTo(beNil())
34+
expect(immutable?.prop1).to(equal("Immutable!"))
35+
expect(immutable?.prop2).to(equal(255))
36+
expect(immutable?.prop3).to(equal(true))
3637

3738
let JSON2 = [ "prop1": "prop1", "prop2": NSNull() ]
3839
let immutable2 = mapper.map(JSON2)
@@ -343,8 +344,8 @@ class ObjectMapperTests: XCTestCase {
343344
let json = Mapper().toJSON(object)
344345
let parsedObject = Mapper<Subclass>().map(json)
345346

346-
expect(object.base).to(equal(parsedObject.base))
347-
expect(object.sub).to(equal(parsedObject.sub))
347+
expect(object.base).to(equal(parsedObject?.base))
348+
expect(object.sub).to(equal(parsedObject?.sub))
348349
}
349350

350351
func testGenericSubclass() {
@@ -355,8 +356,8 @@ class ObjectMapperTests: XCTestCase {
355356
let json = Mapper().toJSON(object)
356357
let parsedObject = Mapper<GenericSubclass<String>>().map(json)
357358

358-
expect(object.base).to(equal(parsedObject.base))
359-
expect(object.sub).to(equal(parsedObject.sub))
359+
expect(object.base).to(equal(parsedObject?.base))
360+
expect(object.sub).to(equal(parsedObject?.sub))
360361
}
361362

362363
func testSubclassWithGenericArrayInSuperclass() {

0 commit comments

Comments
 (0)