https://gqlgen.com

Gqlgen Custom Data Validation — Part 1

In this article, we will create our custom data validation for the gqlgen library.

Before you start reading this, I assume that you know about creating a simple app with gqlgen.

Why Gqlgen?

  • Schema First, which will help us generate code from Graphql Schema that we write before
  • Type Safety; we will rarely see map[string]interface{}; most of the responses will use a model
  • Codegen, most of the repeating part will be generated so that we only focus on the important part of the code

Libraries

Get Started

Initialize a go mod and go get libraries needed

# Initialize
go mod init myapp
go get github.com/99designs/gqlgen
go get github.com/go-playground/validator
# gqlgen init
go run github.com/99designs/gqlgen init

The project directory should look like this for now:

directory after gqlgen init

explanation:

  • gqlgen.yml: config file for gqlgen generator
  • graph/*.graphqls: Pre-written GraphQL schema (user-defined)
  • graph/*.resolvers.go: output of generated GraphQL schema
  • graph/model/models_gen.go: All model will be generated inside this file
  • graph/generated/generated.go: repeating action that generated by gqlgen

Define and Generating Our Schema

graph/user.graphqls

I will use variable to store the user instead of database to make the explanation shorter and more focused on data validation.

@goField is build-in directives by gqlgen that allow us to force generate a resolver.

We will add a go generate for our gqlgen in graph/resolvers.go

package graph//go:generate go run github.com/99designs/gqlgen// This file will not be regenerated automatically.//// It serves as dependency injection for your app, add any dependencies you require here.type Resolver struct{}

To generate the Schema, type this command:

go generate ./...
after go generate ./…

Erase the code from ‘!!! Warning!’ to the end of the file.

Create User Service

graph/schema.resolvers.go :

graph/user.resolvers.go :

After creating the user service (create and get all), we assign the function to the correct resolver.

Testing Our Code

go run server.go# output:
# connect to http://localhost:8080/ for GraphQL playground

Try to access http://localhost:8080 and we will see our graphql Playground.

First we will try to Get All Users :

get all users (empty)

Then it’s confirmed that our code is still working well.

Next we will try to create our first and second user.

create first user
create second user

Then we will Get All Users again :

get all users ()

Custom Validation with Directives

How to add the custom directives?

We will add the custom directives @binding in graph/schema.graphqls.

...
directive @goField(forceResolver: String, name: String) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
directive @binding(constraint: String!) on INPUT_FIELD_DEFINITION | ARGUMENT_DEFINITION
...

And apply the directive to our NewUser model.

input NewUser {
name: String! @binding(constraint: "required,max=20")
email: String! @binding(constraint: "required,email")
age: Int! @binding(constraint: "gte=0,lte=128")
country_id: String! @binding(constraint: "required,iso3166_1_alpha2")
}

Then go generate ./… the code and binding directive will be created.

The only thing we still need to do is create the function for binding and apply it to the directive.

directives/binding.go :

By using github.com/go-playground/validator, the parameter passed by the gqlgen system will be validated through the directives using the validator, available tags can be found on the library itself.

We edit server.go to apply the func to the directives:

We have completed the validation part, now it’s time for a testing:

name ‘required’ failed
age greater than equal ‘0’ failed

But as we can saw from the examples, the error message is not helpful enough. We can fix this thing by adding one more library ‘github.com/go-playground/universal-translatorthat makes the error message more ‘meaningful’.

directives/binding.go :

server.go :

This will solve the error message problem, and we can edit the default translation tag to our custom message.

Try to run again the code, and we will see a different error message now :

age ‘gte’ failed
name ‘required’ failed
name ‘max’ failed
email ‘email’ failed (custom message)

That’s all for the Part-1 of gqlgen data validation, Part-2 will discuss about gqlgen Plugin and how to create plugin with a data validation build-in.

Hope this article help you :)