diff --git a/Sources/AWSSDKSwiftCore/AWSClient.swift b/Sources/AWSSDKSwiftCore/AWSClient.swift index 1572da3c2..c3a00501c 100644 --- a/Sources/AWSSDKSwiftCore/AWSClient.swift +++ b/Sources/AWSSDKSwiftCore/AWSClient.swift @@ -253,7 +253,7 @@ extension AWSClient { } case .query: - var dict = try ctx.input.serializeToDictionary() + var dict = try ctx.input.serializeToFlatDictionary() dict["Action"] = operationName dict["Version"] = apiVersion diff --git a/Sources/AWSSDKSwiftCore/DictionaryConvertible/DictionaryConvertible.swift b/Sources/AWSSDKSwiftCore/DictionaryConvertible/DictionaryConvertible.swift index cb06c1f06..cb7029e2f 100644 --- a/Sources/AWSSDKSwiftCore/DictionaryConvertible/DictionaryConvertible.swift +++ b/Sources/AWSSDKSwiftCore/DictionaryConvertible/DictionaryConvertible.swift @@ -89,6 +89,48 @@ extension DictionarySerializable { } return serialized } + + func serializeToFlatDictionary() throws -> [String: Any] { + func flatten(dictionary: [String: Any]) -> [String: Any] { + var flatted: [String: Any] = [:] + + func destructiveFlatten(dictionary: [String: Any]) { + for (key, value) in dictionary { + switch value { + case let value as [String: Any]: + for (key2, value2) in flatten(dictionary: value) { + switch value2 { + case let value2 as [String: Any]: + destructiveFlatten(dictionary: value2) + + case let values as [Any]: // TODO: values might be dictionary... + for iterator in values.enumerated() { + flatted["\(key).member.\(iterator.offset+1)"] = iterator.element + } + + default: + flatted["\(key).\(key2)"] = value2 + } + } + + case let values as [Any]: // TODO: values might be dictionary... + for iterator in values.enumerated() { + flatted["\(key).member.\(iterator.offset+1)"] = iterator.element + } + + default: + flatted[key] = value + } + } + } + + destructiveFlatten(dictionary: dictionary) + + return flatted + } + + return flatten(dictionary: try self.serializeToDictionary()) + } } public typealias DictionaryConvertible = DictionarySerializable & DictionaryInitializable diff --git a/Tests/AWSSDKSwiftCoreTests/SerializableTests.swift b/Tests/AWSSDKSwiftCoreTests/SerializableTests.swift index 3d7ef5a6e..4ed0f7a1d 100644 --- a/Tests/AWSSDKSwiftCoreTests/SerializableTests.swift +++ b/Tests/AWSSDKSwiftCoreTests/SerializableTests.swift @@ -15,20 +15,40 @@ typealias Serializable = DictionarySerializable & XMLNodeSerializable class SerializableTests: XCTestCase { struct B: Serializable { + public static var parsingHints: [AWSShapeProperty] = [ + AWSShapeProperty(label: "a", required: true, type: .string), + AWSShapeProperty(label: "b", required: false, type: .list), + AWSShapeProperty(label: "c", required: true, type: .list) + ] + let a = "1" let b = [1, 2] let c = ["key": "value"] } struct C: Serializable { + public static var parsingHints: [AWSShapeProperty] = [ + AWSShapeProperty(label: "value", required: true, type: .string) + ] + let value = "hello" } struct D: Serializable { + public static var parsingHints: [AWSShapeProperty] = [ + AWSShapeProperty(label: "value", required: true, type: .string) + ] + let value = "world" } struct A: Serializable { + public static var parsingHints: [AWSShapeProperty] = [ + AWSShapeProperty(label: "structure", required: true, type: .structure), + AWSShapeProperty(label: "structures", required: false, type: .list), + AWSShapeProperty(label: "array", required: true, type: .list) + ] + let structure = B() let structures: [Serializable] = [C(), D()] let array = ["foo", "bar"] @@ -37,7 +57,8 @@ class SerializableTests: XCTestCase { static var allTests : [(String, (SerializableTests) -> () throws -> Void)] { return [ ("testSerializeToXML", testSerializeToXML), - ("testSerializeToDictionaryAndJSON", testSerializeToDictionaryAndJSON) + ("testSerializeToDictionaryAndJSON", testSerializeToDictionaryAndJSON), + ("testSerializeToFlatDictionary", testSerializeToFlatDictionary) ] } @@ -57,4 +78,13 @@ class SerializableTests: XCTestCase { XCTAssertEqual(dict.count, jsonObect.count) } + func testSerializeToFlatDictionary() { + let dict = try! A().serializeToFlatDictionary() + XCTAssertEqual(dict.count, 8) + XCTAssertEqual(dict["structure.a"] as? String, "1") + XCTAssertEqual(dict["structure.c.key"] as? String, "value") + XCTAssertEqual(dict["array.member.1"] as? String, "foo") + XCTAssertEqual(dict["array.member.2"] as? String, "bar") + } + }