Skip to content

Commit

Permalink
Adding additional documentation for int-based enums
Browse files Browse the repository at this point in the history
Int-based enums need an additional marshal/unmarshal functionality in order to work with GraphQL client libraries.
  • Loading branch information
oxisto committed Jan 6, 2025
1 parent 663d013 commit cd7c1d9
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 1 deletion.
39 changes: 39 additions & 0 deletions _examples/enum/model/model.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package model

import (
"encoding/json"
"fmt"
)

type IntTyped int

const (
Expand All @@ -12,6 +17,40 @@ const (
IntUntypedTwo
)

func (t IntTyped) String() string {
switch t {
case IntTypedOne:
return "ONE"
case IntTypedTwo:
return "TWO"
default:
return "UNKNOWN"
}
}

func (t IntTyped) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%s"`, t.String())), nil
}

func (t *IntTyped) UnmarshalJSON(b []byte) (err error) {
var s string

if err = json.Unmarshal(b, &s); err != nil {
return err
}

switch s {
case "ONE":
*t = IntTypedOne
case "TWO":
*t = IntTypedTwo
default:
return fmt.Errorf("unexpected enum value %q", s)
}

return nil
}

type StringTyped string

const (
Expand Down
47 changes: 46 additions & 1 deletion docs/content/recipes/enum.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Both typed and untyped binding are supported.

More examples can be found in [_examples/enum](https://github.com/99designs/gqlgen/tree/master/_examples/enum).

## Binding Targets

Binding target go model enums:

```golang
Expand Down Expand Up @@ -80,4 +82,47 @@ models:
value: ./model.EnumUntypedOne
TWO:
value: ./model.EnumUntypedTwo
```
```
## Additional Notes for int-based Enums
If you want to use the generated input structs that use int-based enums to query your GraphQL server, you need an additional step to convert the int-based enum value into a JSON string representation. Otherwise, most client libraries will send an integer value, which the server will not understand, since it is expecting the string representation (e.g. `ONE` in the above example).

Therefore, we must implement `MarshalJSON` and `UnmarshalJSON` on the typed enum type to convert between both. This is only possible with typed bindings.

```go
func (t EnumTyped) String() string {
switch t {
case EnumTypedOne:
return "ONE"
case EnumTypedTwo:
return "TWO"
default:
return "UNKNOWN"
}
}
func (t EnumTyped) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%s"`, t.String())), nil
}
func (t *EnumTyped) UnmarshalJSON(b []byte) (err error) {
var s string
if err = json.Unmarshal(b, &s); err != nil {
return err
}
switch s {
case "ONE":
*t = EnumTypedOne
case "TWO":
*t = EnumTypedTwo
default:
return fmt.Errorf("unexpected enum value %q", s)
}
return nil
}
```

0 comments on commit cd7c1d9

Please # to comment.