Skip to content

Commit da64650

Browse files
- added support for dictionary of arrays of custom objects
- added test for the above
1 parent 7c19f2e commit da64650

File tree

5 files changed

+183
-149
lines changed

5 files changed

+183
-149
lines changed

ObjectMapper/Core/FromJSON.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,23 @@ internal final class FromJSON {
8383
class func optionalObjectDictionary<N: Mappable>(inout field: Dictionary<String, N>!, object: AnyObject?) {
8484
field = Mapper().mapDictionary(object)
8585
}
86+
87+
/// Dictionary containing Array of Mappable objects
88+
class func objectDictionaryOfArrays<N: Mappable>(inout field: Dictionary<String, [N]>, object: AnyObject?) {
89+
let parsedObjects = Mapper<N>().mapDictionaryOfArrays(object)
90+
91+
if let objects = parsedObjects {
92+
field = objects
93+
}
94+
}
95+
96+
/// Optional Dictionary containing Array of Mappable objects
97+
class func optionalObjectDictionaryOfArrays<N: Mappable>(inout field: Dictionary<String, [N]>?, object: AnyObject?) {
98+
field = Mapper<N>().mapDictionaryOfArrays(object)
99+
}
100+
101+
/// Implicitly unwrapped Dictionary containing Array of Mappable objects
102+
class func optionalObjectDictionaryOfArrays<N: Mappable>(inout field: Dictionary<String, [N]>!, object: AnyObject?) {
103+
field = Mapper<N>().mapDictionaryOfArrays(object)
104+
}
86105
}

ObjectMapper/Core/Mapper.swift

Lines changed: 63 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ public enum MappingType {
1818
case ToJSON
1919
}
2020

21-
/**
22-
* A class used for holding mapping data
23-
*/
21+
22+
/// A class used for holding mapping data
2423
public final class Map {
2524
public let mappingType: MappingType
2625

@@ -36,11 +35,9 @@ public final class Map {
3635
self.JSONDictionary = JSONDictionary
3736
}
3837

39-
/**
40-
* Sets the current mapper value and key.
41-
*
42-
* The Key paramater can be a period separated string (ex. "distance.value") to access sub objects.
43-
*/
38+
39+
/// Sets the current mapper value and key.
40+
/// The Key paramater can be a period separated string (ex. "distance.value") to access sub objects.
4441
public subscript(key: String) -> Map {
4542
// save key and value associated to it
4643
currentKey = key
@@ -82,9 +79,7 @@ public final class Map {
8279
}
8380
}
8481

85-
/**
86-
* Fetch value from JSON dictionary, loop through them until we reach the desired object.
87-
*/
82+
/// Fetch value from JSON dictionary, loop through them until we reach the desired object.
8883
private func valueFor(keyPathComponents: [String], dictionary: [String : AnyObject]) -> AnyObject? {
8984
// Implement it as a tail recursive function.
9085

@@ -109,29 +104,23 @@ private func valueFor(keyPathComponents: [String], dictionary: [String : AnyObje
109104
return nil
110105
}
111106

112-
/**
113-
* The Mapper class provides methods for converting Model objects to JSON and methods for converting JSON to Model objects
114-
*/
107+
/// The Mapper class provides methods for converting Model objects to JSON and methods for converting JSON to Model objects
115108
public final class Mapper<N: Mappable> {
116109
public init(){
117110

118111
}
119112

120113
// MARK: Mapping functions that map to an existing object toObject
121114

122-
/**
123-
* Map a JSON string onto an existing object
124-
*/
115+
/// Map a JSON string onto an existing object
125116
public func map(JSONString: String, var toObject object: N) -> N {
126117
if let JSON = parseJSONDictionary(JSONString) {
127118
return map(JSON, toObject: object)
128119
}
129120
return object
130121
}
131122

132-
/**
133-
* Maps a JSON object to an existing Mappable object if it is a JSON dictionary, or returns the passed object as is
134-
*/
123+
/// Maps a JSON object to an existing Mappable object if it is a JSON dictionary, or returns the passed object as is
135124
public func map(JSON: AnyObject?, var toObject object: N) -> N {
136125
if let JSON = JSON as? [String : AnyObject] {
137126
return map(JSON, toObject: object)
@@ -140,10 +129,8 @@ public final class Mapper<N: Mappable> {
140129
return object
141130
}
142131

143-
/**
144-
* Maps a JSON dictionary to an existing object that conforms to Mappable.
145-
* Usefull for those pesky objects that have crappy designated initializers like NSManagedObject
146-
*/
132+
/// Maps a JSON dictionary to an existing object that conforms to Mappable.
133+
/// Usefull for those pesky objects that have crappy designated initializers like NSManagedObject
147134
public func map(JSONDictionary: [String : AnyObject], var toObject object: N) -> N {
148135
let map = Map(mappingType: .FromJSON, JSONDictionary: JSONDictionary)
149136
object.mapping(map)
@@ -152,29 +139,23 @@ public final class Mapper<N: Mappable> {
152139

153140
//MARK: Mapping functions that create an object
154141

155-
/**
156-
* Map a JSON string to an object that conforms to Mappable
157-
*/
142+
/// Map a JSON string to an object that conforms to Mappable
158143
public func map(JSONString: String) -> N? {
159144
if let JSON = parseJSONDictionary(JSONString) {
160145
return map(JSON)
161146
}
162147
return nil
163148
}
164149

165-
/**
166-
* Map a JSON NSString to an object that conforms to Mappable
167-
*/
150+
/// Map a JSON NSString to an object that conforms to Mappable
168151
public func map(JSONString: NSString) -> N? {
169152
if let string = JSONString as? String {
170153
return map(string)
171154
}
172155
return nil
173156
}
174157

175-
/**
176-
* Maps a JSON object to a Mappable object if it is a JSON dictionary or NSString, or returns nil.
177-
*/
158+
/// Maps a JSON object to a Mappable object if it is a JSON dictionary or NSString, or returns nil.
178159
public func map(JSON: AnyObject?) -> N? {
179160
if let JSON = JSON as? [String : AnyObject] {
180161
return map(JSON)
@@ -183,9 +164,7 @@ public final class Mapper<N: Mappable> {
183164
return nil
184165
}
185166

186-
/**
187-
* Maps a JSON dictionary to an object that conforms to Mappable
188-
*/
167+
/// Maps a JSON dictionary to an object that conforms to Mappable
189168
public func map(JSONDictionary: [String : AnyObject]) -> N? {
190169
let map = Map(mappingType: .FromJSON, JSONDictionary: JSONDictionary)
191170
let object = N(map)
@@ -194,9 +173,7 @@ public final class Mapper<N: Mappable> {
194173

195174
//MARK: Mapping functions for Arrays and Dictionaries
196175

197-
/**
198-
* Maps a JSON array to an object that conforms to Mappable
199-
*/
176+
/// Maps a JSON array to an object that conforms to Mappable
200177
public func mapArray(JSONString: String) -> [N] {
201178
let parsedJSON: AnyObject? = parseJSONString(JSONString)
202179

@@ -213,9 +190,7 @@ public final class Mapper<N: Mappable> {
213190
return []
214191
}
215192

216-
/** Maps a JSON object to an array of Mappable objects if it is an array of
217-
* JSON dictionary, or returns nil.
218-
*/
193+
/// Maps a JSON object to an array of Mappable objects if it is an array of JSON dictionary, or returns nil.
219194
public func mapArray(JSON: AnyObject?) -> [N]? {
220195
if let JSONArray = JSON as? [[String : AnyObject]] {
221196
return mapArray(JSONArray)
@@ -224,17 +199,13 @@ public final class Mapper<N: Mappable> {
224199
return nil
225200
}
226201

227-
/**
228-
* Maps an array of JSON dictionary to an array of object that conforms to Mappable
229-
*/
202+
/// Maps an array of JSON dictionary to an array of Mappable objects
230203
public func mapArray(JSONArray: [[String : AnyObject]]) -> [N] {
231204
// map every element in JSON array to type N
232205
return JSONArray.filterMap(map)
233206
}
234207

235-
/** Maps a JSON object to a dictionary of Mappable objects if it is a JSON
236-
* dictionary of dictionaries, or returns nil.
237-
*/
208+
/// Maps a JSON object to a dictionary of Mappable objects if it is a JSON dictionary of dictionaries, or returns nil.
238209
public func mapDictionary(JSON: AnyObject?) -> [String : N]? {
239210
if let JSONDictionary = JSON as? [String : [String : AnyObject]] {
240211
return mapDictionary(JSONDictionary)
@@ -243,48 +214,61 @@ public final class Mapper<N: Mappable> {
243214
return nil
244215
}
245216

246-
/**
247-
* Maps a JSON dictionary of dictionaries to a dictionary of objects that conform to Mappable.
248-
*/
217+
/// Maps a JSON dictionary of dictionaries to a dictionary of Mappble objects
249218
public func mapDictionary(JSONDictionary: [String : [String : AnyObject]]) -> [String : N] {
250219
// map every value in dictionary to type N
251220
return JSONDictionary.filterMap(map)
252221
}
222+
223+
/// Maps a JSON object to a dictionary of arrays of Mappable objects
224+
public func mapDictionaryOfArrays(JSON: AnyObject?) -> [String : [N]]? {
225+
if let JSONDictionary = JSON as? [String : [[String : AnyObject]]] {
226+
return mapDictionaryOfArrays(JSONDictionary)
227+
}
228+
229+
return nil
230+
}
231+
232+
///Maps a JSON dictionary of arrays to a dictionary of arrays of Mappable objects
233+
public func mapDictionaryOfArrays(JSONDictionary: [String : [[String : AnyObject]]]) -> [String : [N]] {
234+
// map every value in dictionary to type N
235+
return JSONDictionary.filterMap({ mapArray($0) })
236+
}
253237

254238
// MARK: Functions that create JSON from objects
255239

256-
/**
257-
* Maps an object that conforms to Mappable to a JSON dictionary <String : AnyObject>
258-
*/
240+
///Maps an object that conforms to Mappable to a JSON dictionary <String : AnyObject>
259241
public func toJSON(var object: N) -> [String : AnyObject] {
260242
let map = Map(mappingType: .ToJSON, JSONDictionary: [:])
261243
object.mapping(map)
262244
return map.JSONDictionary
263245
}
264246

265-
/**
266-
* Maps an array of Objects to an array of JSON dictionaries [[String : AnyObject]]
267-
*/
247+
///Maps an array of Objects to an array of JSON dictionaries [[String : AnyObject]]
268248
public func toJSONArray(array: [N]) -> [[String : AnyObject]] {
269249
return array.map {
270250
// convert every element in array to JSON dictionary equivalent
271251
self.toJSON($0)
272252
}
273253
}
274254

275-
/**
276-
* Maps a dictionary of Objects that conform to Mappable to a JSON dictionary of dictionaries.
277-
*/
255+
///Maps a dictionary of Objects that conform to Mappable to a JSON dictionary of dictionaries.
278256
public func toJSONDictionary(dictionary: [String : N]) -> [String : [String : AnyObject]] {
279257
return dictionary.map { k, v in
280258
// convert every value in dictionary to its JSON dictionary equivalent
281259
return (k, self.toJSON(v))
282260
}
283261
}
262+
263+
///Maps a dictionary of Objects that conform to Mappable to a JSON dictionary of dictionaries.
264+
public func toJSONDictionaryOfArrays(dictionary: [String : [N]]) -> [String : [[String : AnyObject]]] {
265+
return dictionary.map { k, v in
266+
// convert every value (array) in dictionary to its JSON dictionary equivalent
267+
return (k, self.toJSONArray(v))
268+
}
269+
}
284270

285-
/**
286-
* Maps an Object to a JSON string
287-
*/
271+
/// Maps an Object to a JSON string
288272
public func toJSONString(object: N, prettyPrint: Bool) -> String? {
289273
let JSONDict = toJSON(object)
290274

@@ -306,17 +290,13 @@ public final class Mapper<N: Mappable> {
306290

307291
// MARK: Private utility functions for converting strings to JSON objects
308292

309-
/**
310-
* Convert a JSON String into a Dictionary<String, AnyObject> using NSJSONSerialization
311-
*/
293+
/// Convert a JSON String into a Dictionary<String, AnyObject> using NSJSONSerialization
312294
private func parseJSONDictionary(JSON: String) -> [String : AnyObject]? {
313295
let parsedJSON: AnyObject? = parseJSONString(JSON)
314296
return parseJSONDictionary(parsedJSON)
315297
}
316-
317-
/**
318-
* Convert a JSON Object into a Dictionary<String, AnyObject> using NSJSONSerialization
319-
*/
298+
299+
/// Convert a JSON Object into a Dictionary<String, AnyObject> using NSJSONSerialization
320300
private func parseJSONDictionary(JSON: AnyObject?) -> [String : AnyObject]? {
321301
if let JSONDict = JSON as? [String : AnyObject] {
322302
return JSONDict
@@ -325,9 +305,7 @@ public final class Mapper<N: Mappable> {
325305
return nil
326306
}
327307

328-
/**
329-
* Convert a JSON String into an Object using NSJSONSerialization
330-
*/
308+
/// Convert a JSON String into an Object using NSJSONSerialization
331309
private func parseJSONString(JSON: String) -> AnyObject? {
332310
let data = JSON.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
333311
if let data = data {
@@ -366,6 +344,18 @@ extension Dictionary {
366344
return mapped
367345
}
368346

347+
internal func map<K: Hashable, V>(@noescape f: Element -> (K, [V])) -> [K : [V]] {
348+
var mapped = [K : [V]]()
349+
350+
for element in self {
351+
let newElement = f(element)
352+
mapped[newElement.0] = newElement.1
353+
}
354+
355+
return mapped
356+
}
357+
358+
369359
internal func filterMap<U>(@noescape f: Value -> U?) -> [Key : U] {
370360
var mapped = [Key : U]()
371361

0 commit comments

Comments
 (0)