Better validation and transformation of graphql input values
See original GitHub issueHi guys,
I have spent some time looking for a solution on how to implement data validation in graphql using directives. The idea seems very nice and clear: schema directives define validation rules to be applied to the data, eg
input ConsumerData {
name: String @length(min: 1, max: 20)
}
However current approach described in the documentation refers to output types of directives only and suggests usage of Consumer<GraphQLFieldDefinition.Builder>
together with GraphQLFieldDefinition.dataFetcher
.
Applying the same approach to GraphQLInputObjectField
wouldn’t work since GraphQLInputObjectField
doesn’t have any kind of data transformer.
Would it make sense to add something like
interface DataTransformer<T> {
public T transform(T value)
}
to GraphQLInputObjectField
for the purpose of usage of directives? This could be used in ValuesResolver.coerceValueAstForInputObject
.
To supply a DataTransformer
to ValuesResolver
one could use the same wiring approach as one currently used to update dataFetcher
on GraphQLFieldDefinition
.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:5
- Comments:11 (7 by maintainers)
One good question is where to put the code for input validation. If we copied the previous pattern we would attach it to each field of the
Input
object like we do onGraphqlFieldDefinition
s.But this is insufficient. For example a field like
mutation { someObject(String input)
has only a scalar type so putting code on the input object itself is no good.Looking at the examples above we have
input object
fields regardless of query fieldSo it seems we need a registry that can take a named “node” and associate a validation bit of code with it. Those nodes could be “query fields (and hence their arguments)” , “input object fields” or “input objects” as a whole.
This starts to beg the question of having a
SchemaExecutionRegistry
that contains validation (by field/type name) and potentially later the “data fetchers” we have today again associated by field name.This
SchemaExecutionRegistry
is probably a peer top theGraphqlSchema
or at least a top level object inside the schema (since today you get the schema to get data fetchers).I have thought long and hard on this and tried to design new “SPI” to allow validation of input values.
However after much thought and code tribulation I have come to the position of adding now SPI but in fact doing what you describe
That is the validation is a precursor to DataFetching and that DataFetcher “enhancement” is the way to achieve it.
I have come to beleive this is the right approach because validationof the data to be executed needs to happen when all the query is valid ready to be executed.
The inputs to “input data validation” need to be perfectly “query valid” in GQK terms before you run actual business values validation. I have come to beleive that confusing “GQL query validation” eg structure of the text and inputs is not the same as validation of the input data.
To that end I have a POC in my personal repo
https://github.com/bbakerman/graphql-java-extended-validation
Its exactly what you describe.
I have tried to make it extensible via plugin validation rules. Whether it can truly do that easily requires some like you to help shape it out.
I have started also on a Java EL implementation where you put in Java EL rules in directives and have them run eg
'${args.containsOneOf('a','b')}'
This is a side project of side project at the moment. I would love to collaborate with others to help shape this out into a published library and likely under the graphql-java project eventually.
@zyxist or anyone else on this thread interested in helping?