AWS Amplify and Flutter: Parsing Issues with Nested GraphQL Query Results

AWS Amplify and Flutter: Parsing Issues with Nested GraphQL Query Results


0

I am trying to execute a simple GraphQL query in my Flutter project. The goal is to get a list of customers with a nested list of devices. However, the results are not being parsed properly and i found some inconsistency between appsync and my project appsync calls. I am pretty new to aws and so i am not familiar how to approach this problem the best way. It would be great if someone can guide me a little here :).

I have created a backend using Amplify Studio and imported it into my project. I created the models in my project with "amplify codegen models".

Here is the Schema:

type Customer @model @auth(rules: [{allow: public}]) {
  id: ID!
  devices: [Device] @hasMany(indexName: "byCustomer", fields: ["id"])
  first_name: String
  last_name: String
  email: AWSEmail!
}

type Device @model @auth(rules: [{allow: public}]) {
  id: ID!
  sessions: [Session] @hasMany(indexName: "byDevice", fields: ["id"])
  customer_id: ID @index(name: "byCustomer")
  thing_name: String!
}

Running the desired query in appsync

query MyQuery {
  listCustomers {
    items {
      id
      email
      first_name
      last_name
      devices {
        items {
          id
          thing_name
          customer_id
        }
      }
    }
  }
}

gives me this response, where devices is an object with the items property which is an array of devices:

{
  "data": {
    "listCustomers": {
      "items": [
        {
          "id": "585a6b7e-e3f5-4cd6-9e7b-f1860f559e5c",
          "email": "[email protected]",
          "first_name": "Max",
          "last_name": "Mustermann",
          "devices": {
            "items": [
              {
                "id": "ca7bf7f9-b0c7-4a83-a7cc-a7b7d0678db7",
                "thing_name": "Device_002",
                "customer_id": "585a6b7e-e3f5-4cd6-9e7b-f1860f559e5c"
              },
              {
                "id": "24967d96-29b9-4ef9-b6d2-684002166a40",
                "thing_name": "Device_003",
                "customer_id": "585a6b7e-e3f5-4cd6-9e7b-f1860f559e5c"
              }
            ]
          }
        },
        {
          "id": "fdcca2c9-ec12-4ce2-a439-15f14bc00d55",
          "email": "[email protected]",
          "first_name": "inautequiconsec",
          "last_name": "mollitametmagnaaliq",
          "devices": {
            "items": [
              {
                "id": "520d9441-d026-45b0-9c3c-26f848e8e728",
                "thing_name": "Device_001",
                "customer_id": "fdcca2c9-ec12-4ce2-a439-15f14bc00d55"
              }
            ]
          }
        }
      ]
    }
  }
}

Running the same query from my flutter project:

  Future<void> _refreshCustomerList() async {
    const listCustomers = 'listCustomers';
    const graphQLDocument = '''query MyQuery {
      $listCustomers {
        items {
          id
          email
          first_name
          last_name
          devices {
            items {
              id
              thing_name
              customer_id
            }
          }
        }
      }
    }''';

    final listCustomersRequest = GraphQLRequest<PaginatedResult<Customer>>(
      document: graphQLDocument,
      modelType: const PaginatedModelType(Customer.classType),
      decodePath: listCustomers,
    );

    try {
      final response =
          await Amplify.API.query(request: listCustomersRequest).response;

      if (response.hasErrors) {
        safePrint('errors: ${response.errors}');
        return;
      }

      final data = response.data;
      final items = response.data?.items;
      safePrint('response: $response');
      safePrint('data: $data');
      safePrint('items: $items');

      setState(() {
        // set _customerList
      });
    } on ApiException catch (e) {
      safePrint('Query failed: $e');
    }
  }

results in this logs, where devices is not an object with items in it but an array of devices itself:

flutter: response: GraphQLResponse<PaginatedResult<Customer>> success: {
  "items": [
    {
      "id": "585a6b7e-e3f5-4cd6-9e7b-f1860f559e5c",
      "devices": [
        {
          "id": "ca7bf7f9-b0c7-4a83-a7cc-a7b7d0678db7",
          "sessions": null,
          "customer_id": "585a6b7e-e3f5-4cd6-9e7b-f1860f559e5c",
          "thing_name": "Device_002",
          "createdAt": null,
          "updatedAt": null
        },
        {
          "id": "24967d96-29b9-4ef9-b6d2-684002166a40",
          "sessions": null,
          "customer_id": "585a6b7e-e3f5-4cd6-9e7b-f1860f559e5c",
          "thing_name": "Device_003",
          "createdAt": null,
          "updatedAt": null
        }
      ],
      "first_name": "Max",
      "last_name": "Mustermann",
      "email": "[email protected]",
      "createdAt": null,
      "updatedAt": null
    },
    {
      "id": "fdcca2c9-ec12-4ce2-a439-15f14bc00d55",
      "devices": [
        {
          "id": "520d9441-d026-45b0-9c3c-26f848e8e728",
          "sessions": null,
          "customer_id": "fdcca2c9-ec12-4ce2-a439-15f14bc00d55",
          "thing_name": "Device_001",
          "createdAt": null,
          "updatedAt": null
        }
      ],
      "first_name": "inautequiconsec",
      "last_name": "mollitametmagnaaliq",
      "email": "[email protected]",
      "createdAt": null,
      "updatedAt": null
    }
  ],
  "nextToken": null
}
flutter: data: Instance of 'PaginatedResult<Customer>'
flutter: items: [Customer {id=585a6b7e-e3f5-4cd6-9e7b-f1860f559e5c, first_name=Max, last_name=Mustermann, [email protected], createdAt=null, updatedAt=null}, Customer {id=fdcca2c9-ec12-4ce2-a439-15f14bc00d55, first_name=inautequiconsec, last_name=mollitametmagnaaliq, email=busi[email protected], createdAt=null, updatedAt=null}]

The problem now is, that those devices are not getting parsed properly to be in the Customer Object as seen in the logs. The generated Customer.fromJson looks like this:

  Customer.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        _devices = json['devices'] is List
            ? (json['devices'] as List)
                .where((e) => e?['serializedData'] != null)
                .map((e) => Device.fromJson(
                    new Map<String, dynamic>.from(e['serializedData'])))
                .toList()
            : null,
        _first_name = json['first_name'],
        _last_name = json['last_name'],
        _email = json['email'],
        _createdAt = json['createdAt'] != null
            ? amplify_core.TemporalDateTime.fromString(json['createdAt'])
            : null,
        _updatedAt = json['updatedAt'] != null
            ? amplify_core.TemporalDateTime.fromString(json['updatedAt'])
            : null;

I think the problem is, that for whatever reason the .fromJson function looks for a ‘serializedData’ but there is no property with that name in the response object. I tried getting rid of the check for serializedData but got multiple other errors.

I am really confused why the ‘amplify codegen models’ created the class this way and i am not sure if i should just edit the .fromJson method to a state where it works or if this will cause other issues down the line.

I also tried the call with ModelQueries.list. There i even dont get any devices in my response. I dont know why, and i am not sure if that may be part of the problem:

  Future<void> _getCustomerList() async {
    try {
      final request = ModelQueries.list(Customer.classType);
      final response = await Amplify.API.query(request: request).response;

      final items = response.data?.items;
      if (response.hasErrors) {
        safePrint('errors: ${response.errors}');
        return;
      }

      safePrint('response: $response');
      safePrint('items: $items');

      setState(() {
        //  // set _customerList
      });
    } on ApiException catch (e) {
      safePrint('Query failed: $e');
    }
  }

Logs:

Reloaded 1 of 2701 libraries in 1.425ms (compile: 44 ms, reload: 619 ms, reassemble: 707 ms).
flutter: response: GraphQLResponse<PaginatedResult<Customer>> success: {
  "items": [
    {
      "id": "585a6b7e-e3f5-4cd6-9e7b-f1860f559e5c",
      "devices": null,
      "first_name": "Max",
      "last_name": "Mustermann",
      "email": "[email protected]",
      "createdAt": "2023-10-01T19:07:43.072000000Z",
      "updatedAt": "2023-10-03T17:00:34.083000000Z"
    },
    {
      "id": "fdcca2c9-ec12-4ce2-a439-15f14bc00d55",
      "devices": null,
      "first_name": "inautequiconsec",
      "last_name": "mollitametmagnaaliq",
      "email": "[email protected]",
      "createdAt": "2023-10-01T19:07:43.125000000Z",
      "updatedAt": "2023-10-01T19:07:43.125000000Z"
    }
  ],
  "nextToken": null
}
flutter: items: [Customer {id=585a6b7e-e3f5-4cd6-9e7b-f1860f559e5c, first_name=Max, last_name=Mustermann, [email protected], createdAt=2023-10-01T19:07:43.072000000Z, updatedAt=2023-10-03T17:00:34.083000000Z}, Customer {id=fdcca2c9-ec12-4ce2-a439-15f14bc00d55, first_name=inautequiconsec, last_name=mollitametmagnaaliq, [email protected], createdAt=2023-10-01T19:07:43.125000000Z, updatedAt=2023-10-01T19:07:43.125000000Z}]


Load 2 more related questions


Show fewer related questions

0



Leave a Reply

Your email address will not be published. Required fields are marked *