gql icon indicating copy to clipboard operation
gql copied to clipboard

Unable to set a field to null

Open seanconnollydev opened this issue 4 years ago • 4 comments

Context

I am unable to set a field to null by executing a mutation that includes a null input field value. I believe I should be able to do this, but the generated serializer removes null input fields from request variables. Consider the following input schema:

input CommunityInput {
  name: String!
  websiteUrl: String # <-- Nullable
}

And associated mutation:

updateCommunity(data: CommunityInput!, id: String!): Community!

I am using ferry to create the following request:

final request = GUpdateCommunitySettingsReq(
      (b) => b
        ..vars.id = "communityId"
        ..vars.data.name = "Community Name"
        ..vars.data.websiteUrl = null, // <--- This is null
    );

Problem

This results in a GraphQL request over the wire that strips the websiteUrl entirely. The variables look like this:

{
  "data": {
    "name": "Community Name"
  },
  "id": "a3c5d70e-3417-11eb-ae0f-7bd5cfb"
}

With a raw GraphQL request, the below mutation would set the websiteUrl field to null, which is the behavior I expect when making an equivalent call:

mutation {
  updateCommunity(
    data: {
      name: "Community Name",
      websiteUrl: null
    },
    id: "a3c5d70e-3417-11eb-ae0f-7bd5cfb85ea6"
  ) {
    id
    name
    websiteUrl
  }
}

I traced the issue to the generated serializer for the input type, which looks like this:

class _$GCommunityInputSerializer
    implements StructuredSerializer<GCommunityInput> {
  @override
  final Iterable<Type> types = const [GCommunityInput, _$GCommunityInput];
  @override
  final String wireName = 'GCommunityInput';

  @override
  Iterable<Object> serialize(Serializers serializers, GCommunityInput object,
      {FullType specifiedType = FullType.unspecified}) {
    final result = <Object>[
      'name',
      serializers.serialize(object.name, specifiedType: const FullType(String)),
    ];
    if (object.websiteUrl != null) { // <-- This null check removes the field entirely from the request.
      result
        ..add('websiteUrl')
        ..add(serializers.serialize(object.websiteUrl,
            specifiedType: const FullType(String)));
    }
    return result;
  }

seanconnollydev avatar Feb 11 '21 18:02 seanconnollydev

looks like built_value will re-add this capability https://github.com/google/built_value.dart/issues/604

micimize avatar Apr 13 '21 13:04 micimize

Thanks! Sorry for opening this in probably the wrong repo, it's taken me a bit to figure out what's where here 😄

seanconnollydev avatar Apr 13 '21 16:04 seanconnollydev

You're good – I think it's fair to leave this open until built_value makes it possible so we can track the feature

micimize avatar Apr 13 '21 17:04 micimize

It seems like https://github.com/google/built_value.dart/issues/604 is already merged.

fabiancrx avatar Jul 18 '22 20:07 fabiancrx