Ad

Serializing Scalar JSON In Flutter's Ferry Graphql For Flexible Query

- 1 answer

I have the following JSON scalar:

"""
The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).
"""
scalar JSON

which I am trying to convert since my query is accepting input: JSON. When testing using graphql playground, query is JSON object thus the following works:

query {
  carts(where: {
    owner:{id: "xxx"}
    store:{name: "yyy"}
  }) {
    id
  }
}
# query is the starting from the where: {...}
# build.yaml
# build.yaml
gql_build|schema_builder: #same for gql_build|schema_builder + gql_build|var_builder + ferry_generator|req_builder:
  options:
          type_overrides:
            DateTime:
              name: DateTime
            JSON:
              name: BuiltMap<String, dynamic>
              import: 'package:built_collection/built_collection.dart'
gql_build|serializer_builder:
        enabled: true
        options:
          schema: myapp|lib/graphql/schema.graphql
          custom_serializers:
            - import: 'package:myapp/app/utils/builtmapjson_serializer.dart'
              name: BuiltMapJsonSerializer

This is the custom serializer (builtmapjson_serializer.dart)

//// lib/app/utils/builtmapjson_serializer.dart
import 'package:built_collection/built_collection.dart';
import "package:gql_code_builder/src/serializers/json_serializer.dart";

class BuiltMapJsonSerializer extends JsonSerializer<BuiltMap<String, dynamic>> {
  @override
  BuiltMap<String, dynamic> fromJson(Map<String, dynamic> json) {
    print('MyJsonSerializer fromJson: $json');
    return BuiltMap.of(json);
  }

  @override
  Map<String, dynamic> toJson(BuiltMap<String, dynamic> operation) {
    print('MyJsonSerializer toJson: ${operation.toString()}');
    return operation.asMap();
  }
}

and the usage:

Future testQuery() async {
    Map<String, dynamic> queryMap = {
      "where": {
        "owner": {
          "id": "xxx",
          "store": {"name": "yyy"}
        }
      }
    };
    final req = GFindCartsReq((b) {
      return b..vars.query.addAll(queryMap);
    });
    var resStream = _graphQLService.client.request(req);
    var res = await resStream.first;
    print(
        'linkExceptions: ${res.linkException}'); // Map: LinkException(Bad state: No serializer for '_InternalLinkedHashMap<String, Map<String, Object>>'.)
  }

So whenever I try to query, it is throwing the linkException stated in the comment on the last line of usage. Any idea what should be the way of serializing it?

Ad

Answer

// Write query like this
query FindCarts($owner_id: String!, $store_name: String!) {
  carts(where: {
    owner:{id: $owner_id}
    store:{name: $store_name}
  }) {
    id
  }
}
// And make request like this:
final req = GFindCartsReq((b) => b..vars.store_name = 'XXX'..vars.owner_id = 'YYY');

I think you may be misunderstanding the use case. they are there to serialize and deserialize the response if you want to end up with a Dart object that's different from graphql representation. you may want to try rereading this section: https://ferrygraphql.com/docs/custom-scalars/#create-a-custom-serializer

in the example in the docs, the graphql schema returns an int for the timestamp, but we want to actually use a Date object, so that's the purpose of the serializer. it tells ferry to deserialize the int in our responses to a Date so we can use a Date in our dart code. you could still use a json serializer (like in the examples you linked to) but it still would not be in the way you're trying to use it -- it would be if your schema returns a json string and you want to deserialize the json string. for example, in my case, my graphql schema actually does return a "jsonb" type on some objects. in order to handle that, i'm using built_value's default json_object like this:

(
...
          type_overrides:
            jsonb:
              name: JsonObject
              import: "package:built_value/json_object.dart"
          custom_serializers:
            - import: "package:built_value/src/json_object_serializer.dart"
              name: JsonObjectSerializer
Ad
source: stackoverflow.com
Ad