github.com/fortexxx/gqlgen@v0.10.3-0.20191216030626-ca5ea8b21ead/example/scalars/model/model.go (about) 1 package model 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "strconv" 8 "strings" 9 "time" 10 11 "github.com/99designs/gqlgen/example/scalars/external" 12 "github.com/99designs/gqlgen/graphql" 13 ) 14 15 type Banned bool 16 17 func (b Banned) MarshalGQL(w io.Writer) { 18 if b { 19 w.Write([]byte("true")) 20 } else { 21 w.Write([]byte("false")) 22 } 23 } 24 25 func (b *Banned) UnmarshalGQL(v interface{}) error { 26 switch v := v.(type) { 27 case string: 28 *b = strings.ToLower(v) == "true" 29 return nil 30 case bool: 31 *b = Banned(v) 32 return nil 33 default: 34 return fmt.Errorf("%T is not a bool", v) 35 } 36 } 37 38 type User struct { 39 ID external.ObjectID 40 Name string 41 Created time.Time // direct binding to builtin types with external Marshal/Unmarshal methods 42 IsBanned Banned 43 Address Address 44 Tier Tier 45 } 46 47 // Point is serialized as a simple array, eg [1, 2] 48 type Point struct { 49 X int 50 Y int 51 } 52 53 func (p *Point) UnmarshalGQL(v interface{}) error { 54 pointStr, ok := v.(string) 55 if !ok { 56 return fmt.Errorf("points must be strings") 57 } 58 59 parts := strings.Split(pointStr, ",") 60 61 if len(parts) != 2 { 62 return fmt.Errorf("points must have 2 parts") 63 } 64 65 var err error 66 if p.X, err = strconv.Atoi(parts[0]); err != nil { 67 return err 68 } 69 if p.Y, err = strconv.Atoi(parts[1]); err != nil { 70 return err 71 } 72 return nil 73 } 74 75 // MarshalGQL implements the graphql.Marshaler interface 76 func (p Point) MarshalGQL(w io.Writer) { 77 fmt.Fprintf(w, `"%d,%d"`, p.X, p.Y) 78 } 79 80 // if the type referenced in .gqlgen.yml is a function that returns a marshaller we can use it to encode and decode 81 // onto any existing go type. 82 func MarshalTimestamp(t time.Time) graphql.Marshaler { 83 return graphql.WriterFunc(func(w io.Writer) { 84 io.WriteString(w, strconv.FormatInt(t.Unix(), 10)) 85 }) 86 } 87 88 // Unmarshal{Typename} is only required if the scalar appears as an input. The raw values have already been decoded 89 // from json into int/float64/bool/nil/map[string]interface/[]interface 90 func UnmarshalTimestamp(v interface{}) (time.Time, error) { 91 if tmpStr, ok := v.(int64); ok { 92 return time.Unix(tmpStr, 0), nil 93 } 94 return time.Time{}, errors.New("time should be a unix timestamp") 95 } 96 97 // Lets redefine the base ID type to use an id from an external library 98 func MarshalID(id external.ObjectID) graphql.Marshaler { 99 return graphql.WriterFunc(func(w io.Writer) { 100 io.WriteString(w, strconv.Quote(fmt.Sprintf("=%d=", id))) 101 }) 102 } 103 104 // And the same for the unmarshaler 105 func UnmarshalID(v interface{}) (external.ObjectID, error) { 106 str, ok := v.(string) 107 if !ok { 108 return 0, fmt.Errorf("ids must be strings") 109 } 110 i, err := strconv.Atoi(str[1 : len(str)-1]) 111 return external.ObjectID(i), err 112 } 113 114 type SearchArgs struct { 115 Location *Point 116 CreatedAfter *time.Time 117 IsBanned Banned 118 } 119 120 // A custom enum that uses integers to represent the values in memory but serialize as string for graphql 121 type Tier uint 122 123 const ( 124 TierA Tier = iota 125 TierB Tier = iota 126 TierC Tier = iota 127 ) 128 129 func TierForStr(str string) (Tier, error) { 130 switch str { 131 case "A": 132 return TierA, nil 133 case "B": 134 return TierB, nil 135 case "C": 136 return TierC, nil 137 default: 138 return 0, fmt.Errorf("%s is not a valid Tier", str) 139 } 140 } 141 142 func (e Tier) IsValid() bool { 143 switch e { 144 case TierA, TierB, TierC: 145 return true 146 } 147 return false 148 } 149 150 func (e Tier) String() string { 151 switch e { 152 case TierA: 153 return "A" 154 case TierB: 155 return "B" 156 case TierC: 157 return "C" 158 default: 159 panic("invalid enum value") 160 } 161 } 162 163 func (e *Tier) UnmarshalGQL(v interface{}) error { 164 str, ok := v.(string) 165 if !ok { 166 return fmt.Errorf("enums must be strings") 167 } 168 169 var err error 170 *e, err = TierForStr(str) 171 return err 172 } 173 174 func (e Tier) MarshalGQL(w io.Writer) { 175 fmt.Fprint(w, strconv.Quote(e.String())) 176 }