github.com/maeglindeveloper/gqlgen@v0.13.1-0.20210413081235-57808b12a0a0/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", weight: 10 } }
     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  )
    64  
    65  type YesNo bool
    66  
    67  // UnmarshalGQL implements the graphql.Unmarshaler interface
    68  func (y *YesNo) UnmarshalGQL(v interface{}) error {
    69  	yes, ok := v.(string)
    70  	if !ok {
    71  		return fmt.Errorf("YesNo must be a string")
    72  	}
    73  
    74  	if yes == "yes" {
    75  		*y = true
    76  	} else {
    77  		*y = false
    78  	}
    79  	return nil
    80  }
    81  
    82  // MarshalGQL implements the graphql.Marshaler interface
    83  func (y YesNo) MarshalGQL(w io.Writer) {
    84  	if y {
    85  		w.Write([]byte(`"yes"`))
    86  	} else {
    87  		w.Write([]byte(`"no"`))
    88  	}
    89  }
    90  ```
    91  
    92  and then wire up the type in .gqlgen.yml or via directives like normal:
    93  
    94  ```yaml
    95  models:
    96    YesNo:
    97      model: github.com/me/mypkg.YesNo
    98  ```
    99  
   100  ## Custom scalars with third party types
   101  
   102  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
   103  library (eg string or time.Time). To support this we can build an external marshaler:
   104  
   105  ```go
   106  package mypkg
   107  
   108  import (
   109  	"fmt"
   110  	"io"
   111  	"strings"
   112  
   113  	"github.com/99designs/gqlgen/graphql"
   114  )
   115  
   116  
   117  func MarshalMyCustomBooleanScalar(b bool) graphql.Marshaler {
   118  	return graphql.WriterFunc(func(w io.Writer) {
   119  		if b {
   120  			w.Write([]byte("true"))
   121  		} else {
   122  			w.Write([]byte("false"))
   123  		}
   124  	})
   125  }
   126  
   127  func UnmarshalMyCustomBooleanScalar(v interface{}) (bool, error) {
   128  	switch v := v.(type) {
   129  	case string:
   130  		return "true" == strings.ToLower(v), nil
   131  	case int:
   132  		return v != 0, nil
   133  	case bool:
   134  		return v, nil
   135  	default:
   136  		return false, fmt.Errorf("%T is not a bool", v)
   137  	}
   138  }
   139  ```
   140  
   141  Then in .gqlgen.yml point to the name without the Marshal|Unmarshal in front:
   142  
   143  ```yaml
   144  models:
   145    MyCustomBooleanScalar:
   146      model: github.com/me/mypkg.MyCustomBooleanScalar
   147  ```
   148  
   149  **Note:** you also can un/marshal to pointer types via this approach, simply accept a pointer in your
   150  `Marshal...` func and return one in your `Unmarshal...` func.
   151  
   152  See the [example/scalars](https://github.com/99designs/gqlgen/tree/master/example/scalars) package for more examples.
   153  
   154  ## Unmarshaling Errors
   155  
   156  The errors that occur as part of custom scalar unmarshaling will return a full path to the field.
   157  For example, given the following schema ...
   158  
   159  ```graphql
   160  extend type Mutation{
   161      updateUser(userInput: UserInput!): User!
   162  }
   163  
   164  input UserInput {
   165      name: String!
   166      primaryContactDetails: ContactDetailsInput!
   167      secondaryContactDetails: ContactDetailsInput!
   168  }
   169  
   170  scalar Email
   171  input ContactDetailsInput {
   172      email: Email!
   173  }
   174  ```
   175  
   176  ... and the following variables:
   177  
   178  ```json
   179  
   180  {
   181    "userInput": {
   182      "name": "George",
   183      "primaryContactDetails": {
   184        "email": "not-an-email"
   185      },
   186      "secondaryContactDetails": {
   187        "email": "george@gmail.com"
   188      }
   189    }
   190  }
   191  ```
   192  
   193  ... and an unmarshal function that returns an error if the email is invalid. The mutation will return an error containing the full path:
   194  ```json
   195  {
   196    "message": "email invalid",
   197    "path": [
   198      "updateUser",
   199      "userInput",
   200      "primaryContactDetails",
   201      "email"
   202    ]
   203  }
   204  ```
   205  
   206