Skip to content

Commit

Permalink
Merge
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanhimmelman committed Feb 24, 2017
1 parent 049d4b1 commit f893bc0
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 26 deletions.
49 changes: 44 additions & 5 deletions Sources/ImmutableMappable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -152,23 +152,62 @@ public extension Map {
}
return value
}


// MARK: [[BaseMappable]]
/// Returns a `[[BaseMappable]]` or throws an error.
public func value<T: BaseMappable>(_ key: String, nested: Bool? = nil, delimiter: String = ".",
file: StaticString = #file, function: StaticString = #function,
line: UInt = #line) throws -> [[T]] {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let json2DArray = currentValue as? [[Any]] else {
throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[[Any]]'", file: file,
function: function, line: line)
}
return try json2DArray.map { jsonArray in
try jsonArray.map { jsonObject -> T in
return try Mapper<T>(context: context).mapOrFail(JSONObject: jsonObject)
}
}
}

/// Returns a `[[BaseMappable]]` using transform or throws an error.
public func value<Transform: TransformType>(_ key: String, nested: Bool? = nil, delimiter: String = ".",
using transform: Transform, file: StaticString = #file,
function: StaticString = #function,
line: UInt = #line) throws -> [[Transform.Object]] {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let json2DArray = currentValue as? [[Any]] else {
throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[[Any]]'",
file: file, function: function, line: line)
}
return try json2DArray.enumerated().map { i, jsonArray in
try jsonArray.enumerated().map { j, json -> Transform.Object in
guard let object = transform.transformFromJSON(json) else {
throw MapError(key: "\(key)[\(i)][\(j)]", currentValue: json,
reason: "Cannot transform to '\(Transform.Object.self)' using \(transform)", file: file,
function: function, line: line)
}
return object
}
}
}

}

public extension Mapper where N: ImmutableMappable {

public func map(JSON: [String: Any]) throws -> N {
return try self.mapOrFail(JSON: JSON)
}

public func map(JSONString: String) throws -> N {
return try mapOrFail(JSONString: JSONString)
}

public func map(JSONObject: Any) throws -> N {
return try mapOrFail(JSONObject: JSONObject)
}

// MARK: Array mapping functions

public func mapArray(JSONArray: [[String: Any]]) throws -> [N] {
Expand Down
51 changes: 31 additions & 20 deletions Sources/TransformOperators.swift
Original file line number Diff line number Diff line change
Expand Up @@ -445,46 +445,53 @@ public func <- <Transform: TransformType>(left: inout Array<Transform.Object>!,
}
}

// MARK:- Array of Array of Mappable objects - Array<Array<T: BaseMappable>>> with transforms
// MARK:- Array of Array of objects - Array<Array<T>>> with transforms

/// Array of Array Mappable objects with transform
public func <- <Transform: TransformType>(left: inout Array<Array<Transform.Object>>, right: (Map, Transform)) where Transform.Object: BaseMappable {
/// Array of Array of objects with transform
public func <- <Transform: TransformType>(left: inout [[Transform.Object]], right: (Map, Transform)) {
let (map, transform) = right
if map.mappingType == .fromJSON && map.isKeyPresent, let original2DArray = map.currentValue as? [[Any]]{
switch map.mappingType {
case .toJSON:
left >>> right
case .fromJSON where map.isKeyPresent:
guard let original2DArray = map.currentValue as? [[Any]] else { break }
let transformed2DArray = original2DArray.flatMap { values in
fromJSONArrayWithTransform(values as Any?, transform: transform)
}
FromJSON.basicType(&left, object: transformed2DArray)
} else if map.mappingType == .toJSON {
left >>> right
default:
break
}
}

public func >>> <Transform: TransformType>(left: Array<Array<Transform.Object>>, right: (Map, Transform)) where Transform.Object: BaseMappable {
public func >>> <Transform: TransformType>(left: [[Transform.Object]], right: (Map, Transform)) {
let (map, transform) = right
if map.mappingType == .toJSON {
if map.mappingType == .toJSON{
let transformed2DArray = left.flatMap { values in
toJSONArrayWithTransform(values, transform: transform)
}
ToJSON.basicType(transformed2DArray, map: map)
}
}


/// Optional array of Mappable objects with transform
public func <- <Transform: TransformType>(left:inout Array<Array<Transform.Object>>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
/// Optional array of objects with transform
public func <- <Transform: TransformType>(left: inout [[Transform.Object]]?, right: (Map, Transform)) {
let (map, transform) = right
if map.mappingType == .fromJSON && map.isKeyPresent, let original2DArray = map.currentValue as? [[Any]]{
switch map.mappingType {
case .toJSON:
left >>> right
case .fromJSON where map.isKeyPresent:
guard let original2DArray = map.currentValue as? [[Any]] else { break }
let transformed2DArray = original2DArray.flatMap { values in
fromJSONArrayWithTransform(values as Any?, transform: transform)
}
FromJSON.optionalBasicType(&left, object: transformed2DArray)
} else if map.mappingType == .toJSON {
left >>> right
default:
break
}
}

public func >>> <Transform: TransformType>(left: Array<Array<Transform.Object>>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
public func >>> <Transform: TransformType>(left: [[Transform.Object]]?, right: (Map, Transform)) {
let (map, transform) = right
if map.mappingType == .toJSON {
let transformed2DArray = left?.flatMap { values in
Expand All @@ -495,16 +502,20 @@ public func >>> <Transform: TransformType>(left: Array<Array<Transform.Object>>?
}


/// Implicitly unwrapped Optional array of Mappable objects with transform
public func <- <Transform: TransformType>(left: inout Array<Array<Transform.Object>>!, right: (Map, Transform)) where Transform.Object: BaseMappable {
/// Implicitly unwrapped Optional array of objects with transform
public func <- <Transform: TransformType>(left: inout [[Transform.Object]]!, right: (Map, Transform)) {
let (map, transform) = right
if map.mappingType == .fromJSON && map.isKeyPresent, let original2DArray = map.currentValue as? [[Any]] {
switch map.mappingType {
case .toJSON:
left >>> right
case .fromJSON where map.isKeyPresent:
guard let original2DArray = map.currentValue as? [[Any]] else { break }
let transformed2DArray = original2DArray.flatMap { values in
fromJSONArrayWithTransform(values as Any?, transform: transform)
}
FromJSON.optionalBasicType(&left, object: transformed2DArray)
} else if map.mappingType == .toJSON {
left >>> right
default:
break
}
}

Expand Down
50 changes: 49 additions & 1 deletion Tests/ObjectMapperTests/ImmutableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,16 @@ class ImmutableObjectTests: XCTestCase {

"prop31a": "String A",
"prop31b": "String B",

// [[String]]
"prop32": [["prop32"]],
"prop33": [["prop33"]],
"prop34": [["prop34"]],

// [[Base]]
"prop35": [[["base": "prop35"]]],
"prop36": [[["base": "prop36"]]],
"prop37": [[["base": "prop37"]]],

"non.nested->key": "string",
"nested": [
Expand Down Expand Up @@ -161,6 +171,14 @@ class ImmutableObjectTests: XCTestCase {
XCTAssertEqual(immutable.prop31a.rawValue, StringEnum.A.rawValue)
XCTAssertEqual(immutable.prop31b.rawValue, StringEnum.B.rawValue)

XCTAssertEqual(immutable.prop32[0][0], "prop32_TRANSFORMED")
XCTAssertEqual(immutable.prop33![0][0], "prop33_TRANSFORMED")
XCTAssertEqual(immutable.prop34[0][0], "prop34_TRANSFORMED")

XCTAssertEqual(immutable.prop35[0][0].base, "prop35")
XCTAssertEqual(immutable.prop36![0][0].base, "prop36")
XCTAssertEqual(immutable.prop37[0][0].base, "prop37")

XCTAssertEqual(immutable.nonnestedString, "string")

XCTAssertEqual(immutable.nestedInt, 123)
Expand Down Expand Up @@ -333,6 +351,14 @@ struct Struct {
let prop31a: StringEnum
let prop31b: StringEnum

let prop32: [[String]]
let prop33: [[String]]?
let prop34: [[String]]!

let prop35: [[Base]]
let prop36: [[Base]]?
let prop37: [[Base]]!

var nonnestedString: String
var nestedInt: Int
var nestedString: String
Expand Down Expand Up @@ -390,6 +416,14 @@ extension Struct: ImmutableMappable {

prop31a = try map.value("prop31a")
prop31b = try map.value("prop31b")

prop32 = try map.value("prop32", using: stringTransform)
prop33 = try? map.value("prop33", using: stringTransform)
prop34 = try? map.value("prop34", using: stringTransform)

prop35 = try map.value("prop35")
prop36 = try? map.value("prop36")
prop37 = try? map.value("prop37")

nonnestedString = try map.value("non.nested->key", nested: false)

Expand Down Expand Up @@ -454,6 +488,14 @@ extension Struct: ImmutableMappable {
prop31a >>> map["prop31a"]
prop31b >>> map["prop31b"]

prop32 >>> (map["prop32"], stringTransform)
prop33 >>> (map["prop33"], stringTransform)
prop34 >>> (map["prop34"], stringTransform)

prop35 >>> map["prop35"]
prop36 >>> map["prop36"]
prop37 >>> map["prop37"]

nonnestedString >>> map["non.nested->key", nested: false]

nestedInt >>> map["nested.int"]
Expand All @@ -476,7 +518,7 @@ let stringTransform = TransformOf<String, String>(
return "\(str)_TRANSFORMED"
},
toJSON: { (str: String?) -> String? in
return str?.replacingOccurrences(of: "_TRANSFORMED", with: "", options: [], range: nil)
return str?.replacingOccurrences(of: "_TRANSFORMED", with: "")
}
)

Expand Down Expand Up @@ -506,4 +548,10 @@ private func assertImmutableObjectsEqual(_ lhs: Struct, _ rhs: Struct) {
XCTAssertEqual("\(lhs.prop20)", "\(rhs.prop20)")
XCTAssertEqual("\(lhs.prop21)", "\(rhs.prop21)")
XCTAssertEqual("\(lhs.prop22)", "\(rhs.prop22)")
XCTAssertEqual("\(lhs.prop32)", "\(rhs.prop32)")
XCTAssertEqual("\(lhs.prop33)", "\(rhs.prop33)")
XCTAssertEqual("\(lhs.prop34)", "\(rhs.prop34)")
XCTAssertEqual("\(lhs.prop35)", "\(rhs.prop35)")
XCTAssertEqual("\(lhs.prop36)", "\(rhs.prop36)")
XCTAssertEqual("\(lhs.prop37)", "\(rhs.prop37)")
}

0 comments on commit f893bc0

Please sign in to comment.