amplify-swift
                                
                                 amplify-swift copied to clipboard
                                
                                    amplify-swift copied to clipboard
                            
                            
                            
                        Deserializing Nested Objects in GraphQL for iOS not working
Describe the bug
I've got a scenario in an app I'm creating where 3 objects have nested manyToMany relationships
for example: 1 top level object (TestStructure1) has multiple objects of type TestStructure2 and TestStructure3 objects of type TestStructure3 can have multiple objects of type TestStructure4
when I make a graphQL request in the AppSync console the correct structure is returned, and when I use that same query in swift using GraphQLRequest<JSONValue>, the correct JSON is returned, but when I make that same request as GraphQLRequest<TestStructure1>, 2, 3, and 4 are all nil
For the sake of simplicity, I've recreated this issue with simple test objects types
schema
`type TestStructure4 @model @auth(rules: [{allow: public}]) { id: ID! test4A: String test4B: String teststructure3s: [TestStructure3] @manyToMany(relationName: "TestStructure3TestStructure4") }
type TestStructure3 @model @auth(rules: [{allow: public}]) { id: ID! test3A: String test3B: String teststructure1s: [TestStructure1] @manyToMany(relationName: "TestStructure1TestStructure3") TestStructure4s: [TestStructure4] @manyToMany(relationName: "TestStructure3TestStructure4") }
type TestStructure2 @model @auth(rules: [{allow: public}]) { id: ID! test2A: String test2B: String teststructure1s: [TestStructure1] @manyToMany(relationName: "TestStructure1TestStructure2") }
type TestStructure1 @model @auth(rules: [{allow: public}]) { id: ID! test1A: String Test1B: String TestStructure2s: [TestStructure2] @manyToMany(relationName: "TestStructure1TestStructure2") TestStructure3s: [TestStructure3] @manyToMany(relationName: "TestStructure1TestStructure3") }`
query:
query MyQuery { getTestStructure1(id: "a54982d2-fe9a-4f74-b096-1db1b3e8722b") { TestStructure2s { items { testStructure2 { test2A test2B id } id } } TestStructure3s { items { testStructure3 { test3A test3B TestStructure4s { items { testStructure4 { test4A test4B } } } } } } Test1B id } }
returned json (correct)
{ "data": { "getTestStructure1": { "TestStructure2s": { "items": [ { "testStructure2": { "test2A": "test", "test2B": "test", "id": "4d784086-e105-4b25-bd20-77e20a25ad85" }, "id": "c148b571-3a77-48b1-aa46-09b9ddf855fd" }, { "testStructure2": { "test2A": "test", "test2B": "test", "id": "d340702a-5b7e-4870-b7b6-2e27c19b1357" }, "id": "72c9a71f-04fa-4cba-ac7c-56324cbcdb83" } ] }, "TestStructure3s": { "items": [ { "testStructure3": { "test3A": "test", "test3B": "test", "TestStructure4s": { "items": [ { "testStructure4": { "test4A": "test", "test4B": "test" } } ] } } } ] } } } }
iOS query (all nested objects nil)
extension GraphQLRequest { static func getTestStructure1Full(id: String) -> GraphQLRequest<TestStructure1> { let document = """ query getTestStructure1Full { getTestStructure1(id: "(id)") { TestStructure2s { items { testStructure2 { test2A test2B id } id } } TestStructure3s { items { testStructure3 { test3A test3B TestStructure4s { items { testStructure4 { test4A test4B } } } } } } Test1B id }
    }
    """
    return GraphQLRequest<TestStructure1>(
      document: document,
      variables: ["id": id],
      responseType: TestStructure1.self,
      decodePath: "getTestStructure1"
    )
}
}
Steps To Reproduce
Use schema and query above in iOS
Expected behavior
When the swift return type is set to JSONValue, the object is received and can be deserialized into the object type correctly, when the same query's return type is set to the generated model type, the nested objects are nil
Amplify Framework Version
1.28.0
Amplify Categories
API
Dependency manager
Swift PM
Swift version
5.6.1
CLI version
10.0.0
Xcode version
13.4.1
Relevant log output
<details>
<summary>Log Messages</summary>
INSERT LOG MESSAGES HERE
Is this a regression?
No
Regression additional context
No response
Device
iphone13 simulator
iOS Version
ios 15
Specific to simulators
No response
Additional context
No response
My workaround for this was to create new models that matched the actual JSON being returned by AppSync and deserializing it manually, but if anyone knows what the issue may be or if any more info is needed, please let me know.
Hi @danhaab, taking a look at the selection set you produced, I suggest adding all fields available including the id for nested testStructure3. The swift model type has a required id property it might be failing to decode. Any items selection set should also contain the nextToken. I think the decoding logic also uses __typename (this one might not be a hard requirement for your use case). So to get this to work as expected, basically I think you need to populate the selection set fully.
Have you considered just calling .get(TestStructure1.self, byId: id) to get the GraphQLRequest? This builder creates the selection set for you and you can call it with Amplify.API.query(request: .get(TestStructure1.self, byid: id). this will allow lazy loading of the nested fields. For your nested selection set issue, we are also working on an extension to the .get builder to allow you to specific how many levels of data to return
Closing this due to no activity. Feel free to reach us if the above suggestion does not work for you.