master
master v0.17.63 v0.17.62 v0.17.61 v0.17.60 v0.17.59 v0.17.58 v0.17.57 v0.17.56 v0.17.55 v0.17.54 v0.17.53 v0.17.52 v0.17.51 v0.17.50 v0.17.49 v0.17.48 v0.17.47 v0.17.46 v0.17.45 v0.17.44

Enum binding

Extended enum to model binding tips
[edit]
You are looking at the docs for the unreleased master branch. The latest version is v0.17.63.

Using the following recipe you can bind enum values to specific const or variable. Both typed and untyped binding are supported.

More examples can be found in _examples/enum.

Binding Targets

Binding target go model enums:

package model

type EnumTyped int

const (
	EnumTypedOne EnumTyped = iota + 1
	EnumTypedTwo
)

const (
	EnumUntypedOne = iota + 1
	EnumUntypedTwo
)

Binding using @goModel and @goEnum directives:

directive @goModel(
    model: String
    models: [String!]
) on OBJECT | INPUT_OBJECT | SCALAR | ENUM | INTERFACE | UNION

directive @goEnum(
    value: String
) on ENUM_VALUE

type Query {
    example(arg: EnumUntyped): EnumTyped
}

enum EnumTyped @goModel(model: "./model.EnumTyped") {
    ONE @goEnum(value: "./model.EnumTypedOne")
    TWO @goEnum(value: "./model.EnumTypedTwo")
}

enum EnumUntyped @goModel(model: "github.com/99designs/gqlgen/graphql.Int") {
    ONE @goEnum(value: "./model.EnumUntypedOne")
    TWO @goEnum(value: "./model.EnumUntypedTwo")
}

The same result can be achieved using the config:

models:
  EnumTyped:
    model: ./model.EnumTyped
    enum_values:
      ONE:
        value: ./model.EnumTypedOne
      TWO:
        value: ./model.EnumTypedTwo
  EnumUntyped:
    model: github.com/99designs/gqlgen/graphql.Int
    enum_values:
      ONE:
        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.

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
}