v0.14.0 v0.17.15 v0.17.14 v0.17.13 v0.17.12 v0.17.11 v0.17.10 v0.17.9 v0.17.8 v0.17.7 v0.17.6 v0.17.5 v0.17.4 v0.17.3 v0.17.2 v0.17.1 v0.17.0 v0.16.0 v0.15.1 v0.15.0 master


Mapping GraphQL scalar types to Go types
You are looking at the docs for an older version (v0.14.0). The latest version is v0.17.15.

Built-in helpers

gqlgen ships with some built-in helpers for common custom scalar use-cases, Time, Any, Upload and Map. Adding any of these to a schema will automatically add the marshalling behaviour to Go types.


scalar Time

Maps a Time GraphQL scalar to a Go time.Time struct.


scalar Map

Maps an arbitrary GraphQL value to a map[string]interface{} Go type.


scalar Upload

Maps a Upload GraphQL scalar to a graphql.Upload struct, defined as follows:

type Upload struct {
	File        io.Reader
	Filename    string
	Size        int64
	ContentType string


scalar Any

Maps an arbitrary GraphQL value to a interface{} Go type.

Custom scalars with user defined types

For user defined types you can implement the graphql.Marshaler and graphql.Unmarshaler interfaces and they will be called.

package mypkg

import (

type YesNo bool

// UnmarshalGQL implements the graphql.Unmarshaler interface
func (y *YesNo) UnmarshalGQL(v interface{}) error {
	yes, ok := v.(string)
	if !ok {
		return fmt.Errorf("YesNo must be a string")

	if yes == "yes" {
		*y = true
	} else {
		*y = false
	return nil

// MarshalGQL implements the graphql.Marshaler interface
func (y YesNo) MarshalGQL(w io.Writer) {
	if y {
	} else {

and then wire up the type in .gqlgen.yml or via directives like normal:

    model: github.com/me/mypkg.YesNo

Custom scalars with third party types

Sometimes you are unable to add add methods to a type - perhaps you don’t own the type, or it is part of the standard library (eg string or time.Time). To support this we can build an external marshaler:

package mypkg

import (


func MarshalMyCustomBooleanScalar(b bool) graphql.Marshaler {
	return graphql.WriterFunc(func(w io.Writer) {
		if b {
		} else {

func UnmarshalMyCustomBooleanScalar(v interface{}) (bool, error) {
	switch v := v.(type) {
	case string:
		return "true" == strings.ToLower(v), nil
	case int:
		return v != 0, nil
	case bool:
		return v, nil
		return false, fmt.Errorf("%T is not a bool", v)

Then in .gqlgen.yml point to the name without the Marshal|Unmarshal in front:

    model: github.com/me/mypkg.MyCustomBooleanScalar

Note: you also can un/marshal to pointer types via this approach, simply accept a pointer in your Marshal... func and return one in your Unmarshal... func.

See the example/scalars package for more examples.

Unmarshaling Errors

The errors that occur as part of custom scalar unmarshaling will return a full path to the field. For example, given the following schema …

extend type Mutation{
    updateUser(userInput: UserInput!): User!

input UserInput {
    name: String!
    primaryContactDetails: ContactDetailsInput!
    secondaryContactDetails: ContactDetailsInput!

scalar Email
input ContactDetailsInput {
    email: Email!

… and the following variables:

  "userInput": {
    "name": "George",
    "primaryContactDetails": {
      "email": "not-an-email"
    "secondaryContactDetails": {
      "email": "george@gmail.com"

… and an unmarshal function that returns an error if the email is invalid. The mutation will return an error containing the full path:

  "message": "email invalid",
  "path": [