Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding additional documentation for int-based enums #3470

Merged
merged 3 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions _examples/enum/model/model.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
package model

import (
"encoding/json"
"fmt"
)

StevenACoffman marked this conversation as resolved.
Show resolved Hide resolved
// this file is provided as an example for int-based enums
// but if you instead wanted to support arbitrary
// english words for numbers to integers, consider
// github.com/will-lol/numberconverter/etoi or a similar library
type IntTyped int

const (
Expand All @@ -12,6 +21,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
}
```

Loading