JSON Fails To Parse GraphQL Response After Flutter Libs Upgrade
I upgraded packages in pubspec.yaml and it looks like JSON-parsing for web responses is broken now. I migrated from graphql: ^3.1.0
to graphql: ^4.0.1
and I also use json_annotation: ^3.1.0
.
Here is a good example of the response I get from http client and what I see when I try to get it as a string:
As you can see roles array is not empty and it's 0 value is not null, but since I upgraded my libraries that's what I get without changing any other code.
Here is my GraphQL query file:
query($pushCredential: TwilioPushCredential!) {
user {
id
info {
...UserInfoFragment
}
roles {
... on Client {
...RoleUserFragment
myFitnessPalId
}
... on Coach {
...RoleUserFragment
maxActiveClients
inviteCode
}
}
chatJwt(pushCredential: $pushCredential)
}
}
fragment UserInfoFragment on UserInfo {
email
firstName
lastName
avatar
phone
}
fragment RoleUserFragment on RoleUser {
id
role
}
Here is how I handle the response:
final options = QueryOptions(
document: get_user_info.document,
variables: {'pushCredential': Platform.isIOS ? 'apn' : 'fcm'},
);
final result = await client.query(options);
Logger.debug("getUser response: ${result.data['user']}");
It looks like this ... on Client
and ... on Coach
logic doesn't work in the new GraphQL version. How to fix it and what am I doing wrong?
Answer
This error is caused by the normalize package update in the graphql_flutter, in particular, normalize requires you to specify the possible types map for fragments to work correctly. This is a mapping from the abstract union and interface types to their concrete object types.
interface PersonI {
name: String
age: Int
}
type Employee implements PersonI {
name: String
age: Int
daysOfEmployement: Int
}
type InStoreCustomer implements PersonI {
name: String
age: Int
numberOfPurchases: Int
}
type OnlineCustomer implements PersonI {
name: String
age: Int
numberOfPurchases: Int
}
union CustomerU = OnlineCustomer | InStoreCustomer
the possible types map would be:
const POSSIBLE_TYPES = const {
'CustomerU': {'InStoreCustomer', 'OnlineCustomer'},
'PersonI': {'Employee', 'InStoreCustomer', 'OnlineCustomer'},
}
// Here's how it's parsed to the cache
final client = GraphQLClient(
cache: GraphQLCache(
possibleTypes: POSSIBLE_TYPES,
),
)
You can generate the POSSIBLE_TYPES
map, e.g., using graphql_codegen.
Furthermore, for normalize to correctly resolve the type you should always make sure you're querying the __typename
. Given the example above a query could look something like
query {
people {
__typename # Needed to decide where which entry to update in the cache
... on Employee {
name
age
}
... on Customer {
name
age
}
}
}
if you're not providing the possible type map and introspecting the typename, the cache can't be updated.
Related Questions
- → I can't convert Json to string [OctoberCms]
- → Uncaught TypeError Illegal invocation when send FormData to ajax
- → Laravel Send URL with JSON
- → how to write react component to construct HTML DOM
- → AJAX folder path issue
- → Chaining "Count of Columns" of a Method to Single Query Builder
- → Laravel - bindings file for repositories
- → Good solution to work with rest-api like SPA with redux?
- → getting the correct record in Angular with a json feed and passed data
- → Transformer usage on laravel/dingo API
- → Google options Page not saving - Javascript
- → Ember.js JSON API confusion
- → How can I query Firebase for an equalTo boolean parameter?