Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java Time data types are not supported in mutation input fields because they are not escaped which leads to syntax validation errors #1476

Open
andreloeffelmann opened this issue Mar 22, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@andreloeffelmann
Copy link
Contributor

Issue Description

If an input field for a mutation is e.g. of DateTime type, the generated GraphQL mutation contains the stringified datetime not in escaped strings which leads to a syntax parsing error at the remote GraphQL service.
This happens because GraphQLRequestSerializer.java does not escape these types in public static String getEntry(Object input, boolean useObjectMapper) method and just invokes .toString() on the value.

Example mutation:

mutation {
  updateTest: (update: { createdAt: 2024-03-22T09:41:30.194029200+01:00 }){
  ...
  }
}

But expected:

mutation {
  updateTest: (update: { createdAt: "2024-03-22T09:41:30.194029200+01:00" }){
  ...
  }
}

A possible solution:
Support java.time.Temporal and java.time.TemporalAmount types in public static String getEntry(Object input, boolean useObjectMapper) method of GraphQLRequestSerializer.java, by adapting it e.g. like this:

public static String getEntry(Object input, boolean useObjectMapper) {
        if (input == null) {
            return null;
        } else if (useObjectMapper) {
            return objectMapperWriteValueAsString(input);
        } else if (input instanceof Collection<?>) {
            return serializeCollection((Collection<?>) input, useObjectMapper);
        } else if (input instanceof Map<?, ?>) {
            return serializeMap((Map<?, ?>) input, useObjectMapper);
        } else if (input instanceof Map.Entry<?, ?>) {
            return serializeMapEntry((Map.Entry<?, ?>) input, useObjectMapper);
        } else if (input instanceof Enum<?>) {
            return serializeEnum((Enum<?>) input);
        } else if (input instanceof String) {
            return escapeJsonString(input.toString());
        } else if (input.getClass().getName().equals("scala.Some")) { // TODO: move to Scala Serializer
            // Currently, option only supports primitive types, so that's fine.
            // Now, this kind of case will appear if and only if Seq[Option[Int]] is
            return input.toString().replace("Some(", "").replace(")", "");
        } else if (input.getClass().getName().equals("scala.None$")) {
            return null;
        } else if (input instanceof Temporal || input instanceof TemporalAmount) {
            return escapeJsonString(input.toString());
        } else {
            return input.toString();
        }
    }
@andreloeffelmann andreloeffelmann added the bug Something isn't working label Mar 22, 2024
@rwo-trackunit
Copy link
Contributor

rwo-trackunit commented Mar 22, 2024

I'm not sure if its resolves your issue, but my implementation uses graphql-java-extended-scalars.

So I've setup DateTime in plugin config

<customTypesMapping>
  <DateTime>java.time.OffsetDateTime</DateTime>

And added ExtendedScalars.DateTime to my auto config

import graphql.scalars.ExtendedScalars;

@AutoConfiguration
public class GraphqlAutoConfiguration {
    @Bean
    public RuntimeWiringConfigurer runtimeWiringConfigurer() {
        return wiringBuilder -> wiringBuilder.scalar(ExtendedScalars.DateTime)

and I don't have this stringify issue.

After all, GraphQL only support very few types out of the box, date not being one of them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants