git.sr.ht/~sircmpwn/gqlgen@v0.0.0-20200522192042-c84d29a1c940/docs/content/reference/scalars.md (about) 1 --- 2 linkTitle: Scalars 3 title: Mapping GraphQL scalar types to Go types 4 description: Mapping GraphQL scalar types to Go types 5 menu: { main: { parent: "reference" } } 6 --- 7 8 ## Built-in helpers 9 10 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. 11 12 ### Time 13 14 ```graphql 15 scalar Time 16 ``` 17 18 Maps a `Time` GraphQL scalar to a Go `time.Time` struct. 19 20 ### Map 21 22 ```graphql 23 scalar Map 24 ``` 25 26 Maps an arbitrary GraphQL value to a `map[string]interface{}` Go type. 27 28 ### Upload 29 30 ```graphql 31 scalar Upload 32 ``` 33 34 Maps a `Upload` GraphQL scalar to a `graphql.Upload` struct, defined as follows: 35 36 ```go 37 type Upload struct { 38 File io.Reader 39 Filename string 40 Size int64 41 ContentType string 42 } 43 ``` 44 45 ### Any 46 47 ```graphql 48 scalar Any 49 ``` 50 51 Maps an arbitrary GraphQL value to a `interface{}` Go type. 52 53 ## Custom scalars with user defined types 54 55 For user defined types you can implement the graphql.Marshaler and graphql.Unmarshaler interfaces and they will be called. 56 57 ```go 58 package mypkg 59 60 import ( 61 "fmt" 62 "io" 63 "strings" 64 ) 65 66 type YesNo bool 67 68 // UnmarshalGQL implements the graphql.Unmarshaler interface 69 func (y *YesNo) UnmarshalGQL(v interface{}) error { 70 yes, ok := v.(string) 71 if !ok { 72 return fmt.Errorf("points must be strings") 73 } 74 75 if yes == "yes" { 76 *y = true 77 } else { 78 *y = false 79 } 80 return nil 81 } 82 83 // MarshalGQL implements the graphql.Marshaler interface 84 func (y YesNo) MarshalGQL(w io.Writer) { 85 if y { 86 w.Write([]byte(`"yes"`)) 87 } else { 88 w.Write([]byte(`"no"`)) 89 } 90 } 91 ``` 92 93 and then in .gqlgen.yml point to the name without the Marshal|Unmarshal in front: 94 95 ```yaml 96 models: 97 YesNo: 98 model: github.com/me/mypkg.YesNo 99 ``` 100 101 ## Custom scalars with third party types 102 103 Sometimes you cant add methods to a type because its in another repo, part of the standard 104 library (eg string or time.Time). To do this we can build an external marshaler: 105 106 ```go 107 package mypkg 108 109 import ( 110 "fmt" 111 "io" 112 "strings" 113 114 "git.sr.ht/~sircmpwn/gqlgen/graphql" 115 ) 116 117 118 func MarshalMyCustomBooleanScalar(b bool) graphql.Marshaler { 119 return graphql.WriterFunc(func(w io.Writer) { 120 if b { 121 w.Write([]byte("true")) 122 } else { 123 w.Write([]byte("false")) 124 } 125 }) 126 } 127 128 func UnmarshalMyCustomBooleanScalar(v interface{}) (bool, error) { 129 switch v := v.(type) { 130 case string: 131 return "true" == strings.ToLower(v), nil 132 case int: 133 return v != 0, nil 134 case bool: 135 return v, nil 136 default: 137 return false, fmt.Errorf("%T is not a bool", v) 138 } 139 } 140 ``` 141 142 Then in .gqlgen.yml point to the name without the Marshal|Unmarshal in front: 143 144 ```yaml 145 models: 146 MyCustomBooleanScalar: 147 model: github.com/me/mypkg.MyCustomBooleanScalar 148 ``` 149 150 See the [example/scalars](https://git.sr.ht/~sircmpwn/gqlgen/tree/master/example/scalars) package for more examples.