From 55c91df2acd52d0e82292818f09d9eef95ab66dc Mon Sep 17 00:00:00 2001 From: Suyeol Jeon Date: Sat, 15 Oct 2016 19:23:48 +0900 Subject: [PATCH 1/5] Add support to pass delimiter for nested keys --- Sources/Map.swift | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/Sources/Map.swift b/Sources/Map.swift index 57b9c6c6..0b434456 100644 --- a/Sources/Map.swift +++ b/Sources/Map.swift @@ -43,6 +43,7 @@ public final class Map { public internal(set) var currentValue: Any? public internal(set) var currentKey: String? var keyIsNested = false + public internal(set) var nestedKeyDelimiter: String = "." public var context: MapContext? let toObject: Bool // indicates whether the mapping is being applied to an existing object @@ -58,23 +59,36 @@ public final class Map { /// 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 - let nested = key.contains(".") - return self[key, nested: nested, ignoreNil: false] + return self[key, delimiter: ".", ignoreNil: false] } - + public subscript(key: String, delimiter delimiter: String) -> Map { + let nested = key.contains(delimiter) + return self[key, nested: nested, delimiter: delimiter, ignoreNil: false] + } + public subscript(key: String, nested nested: Bool) -> Map { - return self[key, nested: nested, ignoreNil: false] + return self[key, nested: nested, delimiter: ".", ignoreNil: false] } - - public subscript(key: String, ignoreNil ignoreNil: Bool) -> Map { - let nested = key.contains(".") - return self[key, nested: nested, ignoreNil: ignoreNil] + public subscript(key: String, nested nested: Bool, delimiter delimiter: String) -> Map { + return self[key, nested: nested, delimiter: delimiter, ignoreNil: false] + } + + public subscript(key: String, ignoreNil ignoreNil: Bool) -> Map { + return self[key, delimiter: ".", ignoreNil: ignoreNil] + } + public subscript(key: String, delimiter delimiter: String, ignoreNil ignoreNil: Bool) -> Map { + let nested = key.contains(delimiter) + return self[key, nested: nested, delimiter: delimiter, ignoreNil: ignoreNil] } - - public subscript(key: String, nested nested: Bool, ignoreNil ignoreNil: Bool) -> Map { + + public subscript(key: String, nested nested: Bool, ignoreNil ignoreNil: Bool) -> Map { + return self[key, nested: nested, delimiter: ".", ignoreNil: ignoreNil] + } + public subscript(key: String, nested nested: Bool, delimiter delimiter: String, ignoreNil ignoreNil: Bool) -> Map { // save key and value associated to it currentKey = key keyIsNested = nested + nestedKeyDelimiter = delimiter // check if a value exists for the current key // do this pre-check for performance reasons @@ -85,7 +99,7 @@ public final class Map { currentValue = isNSNull ? nil : object } else { // break down the components of the key that are separated by . - (isKeyPresent, currentValue) = valueFor(ArraySlice(key.components(separatedBy: ".")), dictionary: JSON) + (isKeyPresent, currentValue) = valueFor(ArraySlice(key.components(separatedBy: delimiter)), dictionary: JSON) } // update isKeyPresent if ignoreNil is true From cfeb203dd3c2cd5558c33aa17defb741db462bc5 Mon Sep 17 00:00:00 2001 From: Suyeol Jeon Date: Sat, 15 Oct 2016 19:24:08 +0900 Subject: [PATCH 2/5] Use delimiter in converting to JSON --- Sources/ToJSON.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/ToJSON.swift b/Sources/ToJSON.swift index cdb2960b..4d595325 100644 --- a/Sources/ToJSON.swift +++ b/Sources/ToJSON.swift @@ -29,12 +29,12 @@ import class Foundation.NSNumber private func setValue(_ value: Any, map: Map) { - setValue(value, key: map.currentKey!, checkForNestedKeys: map.keyIsNested, dictionary: &map.JSON) + setValue(value, key: map.currentKey!, checkForNestedKeys: map.keyIsNested, delimiter: map.nestedKeyDelimiter, dictionary: &map.JSON) } -private func setValue(_ value: Any, key: String, checkForNestedKeys: Bool, dictionary: inout [String : Any]) { +private func setValue(_ value: Any, key: String, checkForNestedKeys: Bool, delimiter: String, dictionary: inout [String : Any]) { if checkForNestedKeys { - let keyComponents = ArraySlice(key.characters.split { $0 == "." }) + let keyComponents = ArraySlice(key.components(separatedBy: delimiter).filter { !$0.isEmpty }.map { $0.characters }) setValue(value, forKeyPathComponents: keyComponents, dictionary: &dictionary) } else { dictionary[key] = value From a80e48ac47e66ca9dcd8d10a84c17eca02e6d758 Mon Sep 17 00:00:00 2001 From: Suyeol Jeon Date: Sat, 15 Oct 2016 19:40:02 +0900 Subject: [PATCH 3/5] Add tests for nested key mapping with delimiters --- Tests/NestedKeysTests.swift | 156 ++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/Tests/NestedKeysTests.swift b/Tests/NestedKeysTests.swift index 4f413eae..bd33d4e6 100644 --- a/Tests/NestedKeysTests.swift +++ b/Tests/NestedKeysTests.swift @@ -126,6 +126,125 @@ class NestedKeysTests: XCTestCase { XCTAssertEqual(value.objectDict, valueFromParsedJSON.objectDict) } + func testNestedKeysWithDelimiter() { + let JSON: [String: Any] = [ + "non.nested->key": "string", + "com.hearst.ObjectMapper.nested": [ + "com.hearst.ObjectMapper.int64": NSNumber(value: INT64_MAX), + "com.hearst.ObjectMapper.bool": true, + "com.hearst.ObjectMapper.int": 255, + "com.hearst.ObjectMapper.double": 100.0 as Double, + "com.hearst.ObjectMapper.float": 50.0 as Float, + "com.hearst.ObjectMapper.string": "String!", + + "com.hearst.ObjectMapper.nested": [ + "int64Array": [NSNumber(value: INT64_MAX), NSNumber(value: INT64_MAX - 1), NSNumber(value: INT64_MAX - 10)], + "boolArray": [false, true, false], + "intArray": [1, 2, 3], + "doubleArray": [1.0, 2.0, 3.0], + "floatArray": [1.0 as Float, 2.0 as Float, 3.0 as Float], + "stringArray": ["123", "ABC"], + + "int64Dict": ["1": NSNumber(value: INT64_MAX)], + "boolDict": ["2": true], + "intDict": ["3": 999], + "doubleDict": ["4": 999.999], + "floatDict": ["5": 123.456 as Float], + "stringDict": ["6": "InDict"], + + "int64Enum": 1000, + "intEnum": 255, + "doubleEnum": 100.0, + "floatEnum": 100.0, + "stringEnum": "String B", + + "com.hearst.ObjectMapper.nested": [ + "object": ["value": 987], + "objectArray": [ ["value": 123], ["value": 456] ], + "objectDict": ["key": ["value": 999]] + ] + ] + ] + ] + + let mapper = Mapper() + + let value: DelimiterNestedKeys! = mapper.map(JSONObject: JSON) + XCTAssertNotNil(value) + + XCTAssertEqual(value.nonNestedString, "string") + + XCTAssertEqual(value.int64, NSNumber(value: INT64_MAX)) + XCTAssertEqual(value.bool, true) + XCTAssertEqual(value.int, 255) + XCTAssertEqual(value.double, 100.0 as Double) + XCTAssertEqual(value.float, 50.0 as Float) + XCTAssertEqual(value.string, "String!") + + let int64Array = [NSNumber(value: INT64_MAX), NSNumber(value: INT64_MAX - 1), NSNumber(value: INT64_MAX - 10)] + XCTAssertEqual(value.int64Array, int64Array) + XCTAssertEqual(value.boolArray, [false, true, false]) + XCTAssertEqual(value.intArray, [1, 2, 3]) + XCTAssertEqual(value.doubleArray, [1.0, 2.0, 3.0]) + XCTAssertEqual(value.floatArray, [1.0 as Float, 2.0 as Float, 3.0 as Float]) + XCTAssertEqual(value.stringArray, ["123", "ABC"]) + + XCTAssertEqual(value.int64Dict, ["1": NSNumber(value: INT64_MAX)]) + XCTAssertEqual(value.boolDict, ["2": true]) + XCTAssertEqual(value.intDict, ["3": 999]) + XCTAssertEqual(value.doubleDict, ["4": 999.999]) + XCTAssertEqual(value.floatDict, ["5": 123.456 as Float]) + XCTAssertEqual(value.stringDict, ["6": "InDict"]) + + XCTAssertEqual(value.int64Enum, Int64Enum.b) + XCTAssertEqual(value.intEnum, IntEnum.b) +// Skip tests due to float issue - #591 +// XCTAssertEqual(value.doubleEnum, DoubleEnum.b) +// XCTAssertEqual(value.floatEnum, FloatEnum.b) + XCTAssertEqual(value.stringEnum, StringEnum.B) + + XCTAssertEqual(value.object?.value, 987) + XCTAssertEqual(value.objectArray.map { $0.value }, [123, 456]) + XCTAssertEqual(value.objectDict["key"]?.value, 999) + + let JSONFromValue = mapper.toJSON(value) + let valueFromParsedJSON: DelimiterNestedKeys! = mapper.map(JSON: JSONFromValue) + XCTAssertNotNil(valueFromParsedJSON) + + XCTAssertEqual(value.nonNestedString, valueFromParsedJSON.nonNestedString) + + XCTAssertEqual(value.int64, valueFromParsedJSON.int64) + XCTAssertEqual(value.bool, valueFromParsedJSON.bool) + XCTAssertEqual(value.int, valueFromParsedJSON.int) + XCTAssertEqual(value.double, valueFromParsedJSON.double) + XCTAssertEqual(value.float, valueFromParsedJSON.float) + XCTAssertEqual(value.string, valueFromParsedJSON.string) + + XCTAssertEqual(value.int64Array, valueFromParsedJSON.int64Array) + XCTAssertEqual(value.boolArray, valueFromParsedJSON.boolArray) + XCTAssertEqual(value.intArray, valueFromParsedJSON.intArray) + XCTAssertEqual(value.doubleArray, valueFromParsedJSON.doubleArray) + XCTAssertEqual(value.floatArray, valueFromParsedJSON.floatArray) + XCTAssertEqual(value.stringArray, valueFromParsedJSON.stringArray) + + XCTAssertEqual(value.int64Dict, valueFromParsedJSON.int64Dict) + XCTAssertEqual(value.boolDict, valueFromParsedJSON.boolDict) + XCTAssertEqual(value.intDict, valueFromParsedJSON.intDict) + XCTAssertEqual(value.doubleDict, valueFromParsedJSON.doubleDict) + XCTAssertEqual(value.floatDict, valueFromParsedJSON.floatDict) + XCTAssertEqual(value.stringDict, valueFromParsedJSON.stringDict) + + XCTAssertEqual(value.int64Enum, valueFromParsedJSON.int64Enum) + XCTAssertEqual(value.intEnum, valueFromParsedJSON.intEnum) + XCTAssertEqual(value.doubleEnum, valueFromParsedJSON.doubleEnum) + XCTAssertEqual(value.floatEnum, valueFromParsedJSON.floatEnum) + XCTAssertEqual(value.stringEnum, valueFromParsedJSON.stringEnum) + + XCTAssertEqual(value.object, valueFromParsedJSON.object) + XCTAssertEqual(value.objectArray, valueFromParsedJSON.objectArray) + XCTAssertEqual(value.objectDict, valueFromParsedJSON.objectDict) + } + } class NestedKeys: Mappable { @@ -203,6 +322,43 @@ class NestedKeys: Mappable { } } +class DelimiterNestedKeys: NestedKeys { + override func mapping(map: Map) { + nonNestedString <- map["non.nested->key", nested: false, delimiter: "->"] + + int64 <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.int64", delimiter: "->"] + bool <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.bool", delimiter: "->"] + int <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.int", delimiter: "->"] + double <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.double", delimiter: "->"] + float <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.float", delimiter: "->"] + string <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.string", delimiter: "->"] + + int64Array <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->int64Array", delimiter: "->"] + boolArray <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->boolArray", delimiter: "->"] + intArray <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->intArray", delimiter: "->"] + doubleArray <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->doubleArray", delimiter: "->"] + floatArray <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->floatArray", delimiter: "->"] + stringArray <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->stringArray", delimiter: "->"] + + int64Dict <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->int64Dict", delimiter: "->"] + boolDict <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->boolDict", delimiter: "->"] + intDict <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->intDict", delimiter: "->"] + doubleDict <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->doubleDict", delimiter: "->"] + floatDict <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->floatDict", delimiter: "->"] + stringDict <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->stringDict", delimiter: "->"] + + int64Enum <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->int64Enum", delimiter: "->"] + intEnum <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->intEnum", delimiter: "->"] + doubleEnum <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->doubleEnum", delimiter: "->"] + floatEnum <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->floatEnum", delimiter: "->"] + stringEnum <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->stringEnum", delimiter: "->"] + + object <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->object", delimiter: "->"] + objectArray <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->objectArray", delimiter: "->"] + objectDict <- map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.nested->objectDict", delimiter: "->"] + } +} + class Object: Mappable, Equatable { var value: Int = Int.min From dfe00255245ec23dc23726621abf8dd53a30877f Mon Sep 17 00:00:00 2001 From: Suyeol Jeon Date: Sat, 15 Oct 2016 19:43:38 +0900 Subject: [PATCH 4/5] Add nested key support in ImmutableMappable --- Sources/ImmutableMappable.swift | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/Sources/ImmutableMappable.swift b/Sources/ImmutableMappable.swift index 468936dc..852e0272 100644 --- a/Sources/ImmutableMappable.swift +++ b/Sources/ImmutableMappable.swift @@ -54,15 +54,16 @@ public extension ImmutableMappable { public extension Map { - fileprivate func currentValue(for key: String) -> Any? { - return self[key].currentValue + fileprivate func currentValue(for key: String, nested: Bool? = nil, delimiter: String = ".") -> Any? { + let isNested = nested ?? key.contains(delimiter) + return self[key, nested: isNested, delimiter: delimiter].currentValue } // MARK: Basic /// Returns a value or throws an error. - public func value(_ key: String, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> T { - let currentValue = self.currentValue(for: key) + public func value(_ 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 value = currentValue as? T else { throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '\(T.self)'", file: file, function: function, line: line) } @@ -70,8 +71,8 @@ public extension Map { } /// Returns a transformed value or throws an error. - public func value(_ key: String, using transform: Transform, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> Transform.Object { - let currentValue = self.currentValue(for: key) + public func value(_ 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 value = transform.transformFromJSON(currentValue) else { throw MapError(key: key, currentValue: currentValue, reason: "Cannot transform to '\(Transform.Object.self)' using \(transform)", file: file, function: function, line: line) } @@ -81,16 +82,16 @@ public extension Map { // MARK: BaseMappable /// Returns a `BaseMappable` object or throws an error. - public func value(_ key: String) throws -> T { - let currentValue = self.currentValue(for: key) + public func value(_ key: String, nested: Bool? = nil, delimiter: String = ".") throws -> T { + let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter) return try Mapper().mapOrFail(JSONObject: currentValue) } // MARK: [BaseMappable] /// Returns a `[BaseMappable]` or throws an error. - public func value(_ key: String, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [T] { - let currentValue = self.currentValue(for: key) + public func value(_ 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 jsonArray = currentValue as? [Any] else { throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[Any]'", file: file, function: function, line: line) } @@ -100,8 +101,8 @@ public extension Map { } /// Returns a `[BaseMappable]` using transform or throws an error. - public func value(_ key: String, using transform: Transform, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [Transform.Object] { - let currentValue = self.currentValue(for: key) + public func value(_ 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 jsonArray = currentValue as? [Any] else { throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[Any]'", file: file, function: function, line: line) } @@ -116,8 +117,8 @@ public extension Map { // MARK: [String: BaseMappable] /// Returns a `[String: BaseMappable]` or throws an error. - public func value(_ key: String, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [String: T] { - let currentValue = self.currentValue(for: key) + public func value(_ key: String, nested: Bool? = nil, delimiter: String = ".", file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [String: T] { + let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter) guard let jsonDictionary = currentValue as? [String: Any] else { throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[String: Any]'", file: file, function: function, line: line) } @@ -129,8 +130,8 @@ public extension Map { } /// Returns a `[String: BaseMappable]` using transform or throws an error. - public func value(_ key: String, using transform: Transform, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [String: Transform.Object] { - let currentValue = self.currentValue(for: key) + public func value(_ key: String, nested: Bool? = nil, delimiter: String = ".", using transform: Transform, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [String: Transform.Object] { + let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter) guard let jsonDictionary = currentValue as? [String: Any] else { throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[String: Any]'", file: file, function: function, line: line) } From c21bf08e135070e0bc166b8f832e3a3820de884c Mon Sep 17 00:00:00 2001 From: Suyeol Jeon Date: Sat, 15 Oct 2016 19:54:04 +0900 Subject: [PATCH 5/5] Add tests for nested key in ImmutableMappable --- Tests/ImmutableTests.swift | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/Tests/ImmutableTests.swift b/Tests/ImmutableTests.swift index aa31933f..b309334a 100644 --- a/Tests/ImmutableTests.swift +++ b/Tests/ImmutableTests.swift @@ -74,6 +74,20 @@ class ImmutableObjectTests: XCTestCase { "prop24": 255, "prop25": true, "prop26": 255.0, + + "non.nested->key": "string", + "nested": [ + "int": 123, + "string": "hello", + "array": ["a", "b", "c"], + "dictionary": ["a": 10, "b": 20, "c": 30], + ], + "com.hearst.ObjectMapper.nested": [ + "com.hearst.ObjectMapper.int": 123, + "com.hearst.ObjectMapper.string": "hello", + "array": ["a", "b", "c"], + "dictionary": ["a": 10, "b": 20, "c": 30], + ] ] func testImmutableMappable() { @@ -115,6 +129,18 @@ class ImmutableObjectTests: XCTestCase { XCTAssertEqual(immutable.prop24!, 255) XCTAssertEqual(immutable.prop25!, true) XCTAssertEqual(immutable.prop26!, 255.0) + + XCTAssertEqual(immutable.nonnestedString, "string") + + XCTAssertEqual(immutable.nestedInt, 123) + XCTAssertEqual(immutable.nestedString, "hello") + XCTAssertEqual(immutable.nestedArray, ["a", "b", "c"]) + XCTAssertEqual(immutable.nestedDictionary, ["a": 10, "b": 20, "c": 30]) + + XCTAssertEqual(immutable.delimiterNestedInt, 123) + XCTAssertEqual(immutable.delimiterNestedString, "hello") + XCTAssertEqual(immutable.delimiterNestedArray, ["a", "b", "c"]) + XCTAssertEqual(immutable.delimiterNestedDictionary, ["a": 10, "b": 20, "c": 30]) let JSON2: [String: Any] = [ "prop1": "prop1", "prop2": NSNull() ] let immutable2 = try? mapper.map(JSON: JSON2) @@ -171,6 +197,17 @@ struct Struct { var prop24: Int? var prop25: Bool? var prop26: Double? + + var nonnestedString: String + var nestedInt: Int + var nestedString: String + var nestedArray: [String] + var nestedDictionary: [String: Int] + + var delimiterNestedInt: Int + var delimiterNestedString: String + var delimiterNestedArray: [String] + var delimiterNestedDictionary: [String: Int] } extension Struct: ImmutableMappable { @@ -203,6 +240,18 @@ extension Struct: ImmutableMappable { prop20 = try map.value("prop20") prop21 = try? map.value("prop21") prop22 = try? map.value("prop22") + + nonnestedString = try map.value("non.nested->key", nested: false) + + nestedInt = try map.value("nested.int") + nestedString = try map.value("nested.string") + nestedArray = try map.value("nested.array") + nestedDictionary = try map.value("nested.dictionary") + + delimiterNestedInt = try map.value("com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.int", delimiter: "->") + delimiterNestedString = try map.value("com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.string", delimiter: "->") + delimiterNestedArray = try map.value("com.hearst.ObjectMapper.nested->array", delimiter: "->") + delimiterNestedDictionary = try map.value("com.hearst.ObjectMapper.nested->dictionary", delimiter: "->") } mutating func mapping(map: Map) { @@ -239,6 +288,18 @@ extension Struct: ImmutableMappable { prop20 >>> map["prop20"] prop21 >>> map["prop21"] prop22 >>> map["prop22"] + + nonnestedString >>> map["non.nested->key", nested: false] + + nestedInt >>> map["nested.int"] + nestedString >>> map["nested.string"] + nestedArray >>> map["nested.array"] + nestedDictionary >>> map["nested.dictionary"] + + delimiterNestedInt >>> map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.int", delimiter: "->"] + delimiterNestedString >>> map["com.hearst.ObjectMapper.nested->com.hearst.ObjectMapper.string", delimiter: "->"] + delimiterNestedArray >>> map["com.hearst.ObjectMapper.nested->array", delimiter: "->"] + delimiterNestedDictionary >>> map["com.hearst.ObjectMapper.nested->dictionary", delimiter: "->"] } }