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?

Gqlgen is a powerful library to generate a graphql API architecture.

  • 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

Repo: https://github.com/david-yappeter/gqlgen-validation-example

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/schema.graphqls

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

service/user.go :

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

Until this point, we will test our code without a validation yet.

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

Gqlgen supports Custom Directives which allow us to create our data validation for an input.

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 :)

--

--

--

Just a normal Go Programmer 👨‍💻

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Deploy Drupal Website in Container Environment

dksnap: Docker Snapshots for Development and Test Data

The peril in counting source lines on an OSS project

Building a Go Web API with the Digital Ocean App Platform

3W. What it feels like to be lost in the world of tech.

Multiplexing & Windows Server Licensing

Digital Archivability

9 Things Every Programmer Should Know

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
David Yappeter

David Yappeter

Just a normal Go Programmer 👨‍💻

More from Medium

GoFrame 101: Log management

Level-based logging in Go with Uber Zap

API development with type-safety across the entire stack

State of Golang linters and the differences between them — SourceLevel