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.
Time
scalar Time
Maps a Time
GraphQL scalar to a Go time.Time
struct.
Map
scalar Map
Maps an arbitrary GraphQL value to a map[string]interface{}
Go type.
Upload
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
}
Any
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 (
"fmt"
"io"
"strings"
)
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("points must be strings")
}
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 {
w.Write([]byte(`"yes"`))
} else {
w.Write([]byte(`"no"`))
}
}
and then in .gqlgen.yml point to the name without the Marshal|Unmarshal in front:
models:
YesNo:
model: github.com/me/mypkg.YesNo
Custom scalars with third party types
Sometimes you cant add methods to a type because its in another repo, part of the standard library (eg string or time.Time). To do this we can build an external marshaler:
package mypkg
import (
"fmt"
"io"
"strings"
"github.com/99designs/gqlgen/graphql"
)
func MarshalMyCustomBooleanScalar(b bool) graphql.Marshaler {
return graphql.WriterFunc(func(w io.Writer) {
if b {
w.Write([]byte("true"))
} else {
w.Write([]byte("false"))
}
})
}
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
default:
return false, fmt.Errorf("%T is not a bool", v)
}
}
Then in .gqlgen.yml point to the name without the Marshal|Unmarshal in front:
models:
MyCustomBooleanScalar:
model: github.com/me/mypkg.MyCustomBooleanScalar
See the example/scalars package for more examples.