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