GraphQL SPQR Unable to serialize ZonedDateTime as expected

1.4k Views Asked by At

I'm on graphql-spqr-0.10.0 and using code-first approach and here is a sample type that clients can query.

@GraphQLType(name = "Activity", description = "Some activity")
public class SomeActivity {

  @GraphQLQuery(description = "Unique id")
  private @NotNull Long id = null;

  @GraphQLQuery(description = "Activity name")
  private @NotNull String name = null;

  @GraphQLScalar @GraphQLQuery(description = "Activity start date time")
  private @NotNull ZonedDateTime startTime = null;

  ...
}

I have graphql-java-extended-scalars(version 1.0) in classpath and i read in one of the thread that i can mark ZonedDateTime field with @GraphQLScalar for it to get serialized with graphql.scalars.datetime.DateTimeScalar & produce a ISO_OFFSET_DATE_TIME date format.

Here is the actual response format which i dont believe is in desired ISO format "startTime": "2017-12-29T16:59:57-06:00[America/Chicago]"

Is this the correct way of using extended scalars ?

2

There are 2 best solutions below

0
On

You should not use @GraphQLScalar here. That annotation is used to force a complex type to be treated as a scalar of a dynamic structure. ZonedDateTime is already treated as a scalar by SPQR with properly implemented coercion, so adding @GraphQLScalar messes it up.

Also, you do not really need the extended scalars lib unless you for some reason prefer that implementation over SPQR's (and I think they're actually equivalent). In that case, your approach of using a custom mapper is correct.

0
On

I ended up solving this by defining a Custom TypeMapper class like below. Although i have no idea if this is the correct way to solve this. Then registered a new ZonedDateTimeTypeMapper instance with GraphQLSchemaGenerator().withTypeMappers()

public class ZonedDateTimeTypeMapper implements TypeMapper {

    private static final GraphQLScalarType type = new graphql.scalars.datetime.DateTimeScalar();

    @Override
    public boolean supports(AnnotatedType type) {
        return type.getType() == ZonedDateTime.class;
    }

    @Override
    public GraphQLInputType toGraphQLInputType(AnnotatedType javaType, OperationMapper operationMapper,
            Set<Class<? extends TypeMapper>> mappersToSkip, BuildContext buildContext) {
        return type;
    }

    @Override
    public GraphQLOutputType toGraphQLType(AnnotatedType javaType, OperationMapper operationMapper,
            Set<Class<? extends TypeMapper>> mappersToSkip, BuildContext buildContext) {
        return type;
    }
}