Skip to content

Commit

Permalink
Merge pull request #124 from Hearst-DD/dictionary-of-arrays
Browse files Browse the repository at this point in the history
Dictionary of arrays
  • Loading branch information
tristanhimmelman committed May 17, 2015
2 parents 7c19f2e + b3e045f commit 3d80294
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 149 deletions.
19 changes: 19 additions & 0 deletions ObjectMapper/Core/FromJSON.swift
Expand Up @@ -83,4 +83,23 @@ internal final class FromJSON {
class func optionalObjectDictionary<N: Mappable>(inout field: Dictionary<String, N>!, object: AnyObject?) {
field = Mapper().mapDictionary(object)
}

/// Dictionary containing Array of Mappable objects
class func objectDictionaryOfArrays<N: Mappable>(inout field: Dictionary<String, [N]>, object: AnyObject?) {
let parsedObjects = Mapper<N>().mapDictionaryOfArrays(object)

if let objects = parsedObjects {
field = objects
}
}

/// Optional Dictionary containing Array of Mappable objects
class func optionalObjectDictionaryOfArrays<N: Mappable>(inout field: Dictionary<String, [N]>?, object: AnyObject?) {
field = Mapper<N>().mapDictionaryOfArrays(object)
}

/// Implicitly unwrapped Dictionary containing Array of Mappable objects
class func optionalObjectDictionaryOfArrays<N: Mappable>(inout field: Dictionary<String, [N]>!, object: AnyObject?) {
field = Mapper<N>().mapDictionaryOfArrays(object)
}
}
136 changes: 63 additions & 73 deletions ObjectMapper/Core/Mapper.swift
Expand Up @@ -18,9 +18,8 @@ public enum MappingType {
case ToJSON
}

/**
* A class used for holding mapping data
*/

/// A class used for holding mapping data
public final class Map {
public let mappingType: MappingType

Expand All @@ -36,11 +35,9 @@ public final class Map {
self.JSONDictionary = JSONDictionary
}

/**
* Sets the current mapper value and key.
*
* The Key paramater can be a period separated string (ex. "distance.value") to access sub objects.
*/

/// Sets the current mapper value and key.
/// The Key paramater can be a period separated string (ex. "distance.value") to access sub objects.
public subscript(key: String) -> Map {
// save key and value associated to it
currentKey = key
Expand Down Expand Up @@ -82,9 +79,7 @@ public final class Map {
}
}

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

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

/**
* The Mapper class provides methods for converting Model objects to JSON and methods for converting JSON to Model objects
*/
/// The Mapper class provides methods for converting Model objects to JSON and methods for converting JSON to Model objects
public final class Mapper<N: Mappable> {
public init(){

}

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

/**
* Map a JSON string onto an existing object
*/
/// Map a JSON string onto an existing object
public func map(JSONString: String, var toObject object: N) -> N {
if let JSON = parseJSONDictionary(JSONString) {
return map(JSON, toObject: object)
}
return object
}

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

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

//MARK: Mapping functions that create an object

/**
* Map a JSON string to an object that conforms to Mappable
*/
/// Map a JSON string to an object that conforms to Mappable
public func map(JSONString: String) -> N? {
if let JSON = parseJSONDictionary(JSONString) {
return map(JSON)
}
return nil
}

/**
* Map a JSON NSString to an object that conforms to Mappable
*/
/// Map a JSON NSString to an object that conforms to Mappable
public func map(JSONString: NSString) -> N? {
if let string = JSONString as? String {
return map(string)
}
return nil
}

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

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

//MARK: Mapping functions for Arrays and Dictionaries

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

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

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

/**
* Maps an array of JSON dictionary to an array of object that conforms to Mappable
*/
/// Maps an array of JSON dictionary to an array of Mappable objects
public func mapArray(JSONArray: [[String : AnyObject]]) -> [N] {
// map every element in JSON array to type N
return JSONArray.filterMap(map)
}

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

/**
* Maps a JSON dictionary of dictionaries to a dictionary of objects that conform to Mappable.
*/
/// Maps a JSON dictionary of dictionaries to a dictionary of Mappble objects
public func mapDictionary(JSONDictionary: [String : [String : AnyObject]]) -> [String : N] {
// map every value in dictionary to type N
return JSONDictionary.filterMap(map)
}

/// Maps a JSON object to a dictionary of arrays of Mappable objects
public func mapDictionaryOfArrays(JSON: AnyObject?) -> [String : [N]]? {
if let JSONDictionary = JSON as? [String : [[String : AnyObject]]] {
return mapDictionaryOfArrays(JSONDictionary)
}

return nil
}

///Maps a JSON dictionary of arrays to a dictionary of arrays of Mappable objects
public func mapDictionaryOfArrays(JSONDictionary: [String : [[String : AnyObject]]]) -> [String : [N]] {
// map every value in dictionary to type N
return JSONDictionary.filterMap({ mapArray($0) })
}

// MARK: Functions that create JSON from objects

/**
* Maps an object that conforms to Mappable to a JSON dictionary <String : AnyObject>
*/
///Maps an object that conforms to Mappable to a JSON dictionary <String : AnyObject>
public func toJSON(var object: N) -> [String : AnyObject] {
let map = Map(mappingType: .ToJSON, JSONDictionary: [:])
object.mapping(map)
return map.JSONDictionary
}

/**
* Maps an array of Objects to an array of JSON dictionaries [[String : AnyObject]]
*/
///Maps an array of Objects to an array of JSON dictionaries [[String : AnyObject]]
public func toJSONArray(array: [N]) -> [[String : AnyObject]] {
return array.map {
// convert every element in array to JSON dictionary equivalent
self.toJSON($0)
}
}

/**
* Maps a dictionary of Objects that conform to Mappable to a JSON dictionary of dictionaries.
*/
///Maps a dictionary of Objects that conform to Mappable to a JSON dictionary of dictionaries.
public func toJSONDictionary(dictionary: [String : N]) -> [String : [String : AnyObject]] {
return dictionary.map { k, v in
// convert every value in dictionary to its JSON dictionary equivalent
return (k, self.toJSON(v))
}
}

///Maps a dictionary of Objects that conform to Mappable to a JSON dictionary of dictionaries.
public func toJSONDictionaryOfArrays(dictionary: [String : [N]]) -> [String : [[String : AnyObject]]] {
return dictionary.map { k, v in
// convert every value (array) in dictionary to its JSON dictionary equivalent
return (k, self.toJSONArray(v))
}
}

/**
* Maps an Object to a JSON string
*/
/// Maps an Object to a JSON string
public func toJSONString(object: N, prettyPrint: Bool) -> String? {
let JSONDict = toJSON(object)

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

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

/**
* Convert a JSON String into a Dictionary<String, AnyObject> using NSJSONSerialization
*/
/// Convert a JSON String into a Dictionary<String, AnyObject> using NSJSONSerialization
private func parseJSONDictionary(JSON: String) -> [String : AnyObject]? {
let parsedJSON: AnyObject? = parseJSONString(JSON)
return parseJSONDictionary(parsedJSON)
}

/**
* Convert a JSON Object into a Dictionary<String, AnyObject> using NSJSONSerialization
*/

/// Convert a JSON Object into a Dictionary<String, AnyObject> using NSJSONSerialization
private func parseJSONDictionary(JSON: AnyObject?) -> [String : AnyObject]? {
if let JSONDict = JSON as? [String : AnyObject] {
return JSONDict
Expand All @@ -325,9 +305,7 @@ public final class Mapper<N: Mappable> {
return nil
}

/**
* Convert a JSON String into an Object using NSJSONSerialization
*/
/// Convert a JSON String into an Object using NSJSONSerialization
private func parseJSONString(JSON: String) -> AnyObject? {
let data = JSON.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
if let data = data {
Expand Down Expand Up @@ -366,6 +344,18 @@ extension Dictionary {
return mapped
}

internal func map<K: Hashable, V>(@noescape f: Element -> (K, [V])) -> [K : [V]] {
var mapped = [K : [V]]()

for element in self {
let newElement = f(element)
mapped[newElement.0] = newElement.1
}

return mapped
}


internal func filterMap<U>(@noescape f: Value -> U?) -> [Key : U] {
var mapped = [Key : U]()

Expand Down

0 comments on commit 3d80294

Please sign in to comment.