question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Pass context into scalar coercing

See original GitHub issue

Making scalar coercion more powerful

It would be a huge advantage to be able to access the context during serializing/deserializing scalars. It would allow to reduce a lot of additional type conversion that must happen in data fetchers on input and output because it requires some contextual information.

Use cases:

Converting date time to client’s time zone

Some applications need to be aware of the current user time zone. This is for example necessary when aggregating calendar events into dates. It just cannot be done in UTC.

The application could internally work with java.time.Instant. During the conversion from the literal to Java type the context object could provide the current client time-zone and convert it to the correct Instant thus keeping the conversion logic in one place.

GraphQLScalarType
    .newScalar()
    .name("DateTime")
    .coercing(new Coercing<Instant, String>() {
        @Override
        public String serialize(Object instant, Context context) {
            if (instant instanceof Instant) {
                ((Instant) instant).atZone(context.getZoneId()).toString();
            }
            // throw
        }
        @Override
        public Instant parseValue(Object input, Context context) {
            LocalDateTime.parse(input).atZone(context.getZoneId).toInstant();
        }
    })
    .build();

Translating strings into client’s locale

Similarly, Strings could be translated on output by using a special type internally MessageBundleKey and converting it to GraphQL string in the coercion. By being able to access the context it would be possible to determine the client locale and translate the message bundle key type into GraphQL string in the correct language.

GraphQLScalarType
    .newScalar()
    .name("LocalizedString")
    .coercing(new Coercing<MessageBundleKey, String>() {
        @Override
        public String serialize(Object key, Context context) {
            return messageBundle.getMessage(key, context.getLocale());
        }
    })
    .build();

Workaround

The only current workaround is to inject the context in a different way. For example using thread local global variables. Spring already offers a similar mechanism using the LocaleContextHolder class. The disadvantage is that it relies on the fact that each thread has a separate context which is not true in a reactive app or when using subscriptions.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
bbakermancommented, May 23, 2020

I agree with this sentiment - the Coercing is a SPI and like the DataFetcher SPI you need context for more extended cases.

The original code was based on the graphql-js implementation and simple String/Int scalars do not need it. But as you say a DateTime based on the current callers Locale needs context.

The trick here would be migration to this. All the Scalars existing today do not expect a context (we would probably call it ScalarEnvironment to ape DataFetchingEnvironment) and hence that MUST continue

That said we already have a example where we have done this

graphql.schema.Coercing#parseLiteral(java.lang.Object, java.util.Map<java.lang.String,java.lang.Object>)

which is defaulted on the interface. We would need to do the same

1reaction
bbakermancommented, Aug 20, 2022

Lets leave this open UNTIL we merge that PR - its likely but not yet done

Read more comments on GitHub >

github_iconTop Results From Across the Web

Async scalars with access to context and info ? #2663 - GitHub
Custom scalars, which are objects, don't have access to info or context (or anything request-related) and their functions like serialize ...
Read more >
Perl list in boolean (scalar) context in while loop - Stack Overflow
Scalar context doesn't coerce lists into their count; scalar context causes the operators to return a scalar from the start.
Read more >
Scalar and List context in Perl, the size of an array - Perl Maven
An array in SCALAR context returns the number of elements in it. This will be very important when you look at passing parameters...
Read more >
Scalars - Hot Chocolate - ChilliCream GraphQL Platform
The main purpose of a scalar is to define how a value is serialized and ... but can be coerced to their expected...
Read more >
Adding Custom Scalars - DGS Framework
It is easy to add a custom scalar type in the DGS framework: Create a class that implements the graphql. schema. Coercing interface...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found