diff --git a/codegen/util.go b/codegen/util.go index fa2ceed3dfe..8a60cd198a8 100644 --- a/codegen/util.go +++ b/codegen/util.go @@ -41,6 +41,7 @@ func findGoInterface(def types.Type) (*types.Interface, error) { func equalFieldName(source, target string) bool { source = strings.ReplaceAll(source, "_", "") + source = strings.ReplaceAll(source, ",omitempty", "") target = strings.ReplaceAll(target, "_", "") return strings.EqualFold(source, target) } diff --git a/integration/generated.go b/integration/generated.go index 2190f107539..5686d6907eb 100644 --- a/integration/generated.go +++ b/integration/generated.go @@ -16,6 +16,7 @@ import ( "github.com/99designs/gqlgen/graphql/introspection" models "github.com/99designs/gqlgen/integration/models-go" "github.com/99designs/gqlgen/integration/remote_api" + "github.com/99designs/gqlgen/integration/testomitempty" gqlparser "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" ) @@ -64,6 +65,10 @@ type ComplexityRoot struct { Viewer func(childComplexity int) int } + RemoteModelWithOmitempty struct { + Description func(childComplexity int) int + } + User struct { Likes func(childComplexity int) int Name func(childComplexity int) int @@ -197,6 +202,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.Viewer(childComplexity), true + case "RemoteModelWithOmitempty.newDesc": + if e.complexity.RemoteModelWithOmitempty.Description == nil { + break + } + + return e.complexity.RemoteModelWithOmitempty.Description(childComplexity), true + case "User.likes": if e.complexity.User.Likes == nil { break @@ -272,7 +284,7 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil } -//go:embed "schema.graphql" "user.graphql" +//go:embed "schema.graphql" "user.graphql" "testomitempty.graphql" var sourcesFS embed.FS func sourceData(filename string) string { @@ -286,6 +298,7 @@ func sourceData(filename string) string { var sources = []*ast.Source{ {Name: "schema.graphql", Input: sourceData("schema.graphql"), BuiltIn: false}, {Name: "user.graphql", Input: sourceData("user.graphql"), BuiltIn: false}, + {Name: "testomitempty.graphql", Input: sourceData("testomitempty.graphql"), BuiltIn: false}, } var parsedSchema = gqlparser.MustLoadSchema(sources...) @@ -1045,6 +1058,47 @@ func (ec *executionContext) fieldContext_Query___schema(ctx context.Context, fie return fc, nil } +func (ec *executionContext) _RemoteModelWithOmitempty_newDesc(ctx context.Context, field graphql.CollectedField, obj *testomitempty.RemoteModelWithOmitempty) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_RemoteModelWithOmitempty_newDesc(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalOString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_RemoteModelWithOmitempty_newDesc(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "RemoteModelWithOmitempty", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _User_name(ctx context.Context, field graphql.CollectedField, obj *remote_api.User) (ret graphql.Marshaler) { fc, err := ec.fieldContext_User_name(ctx, field) if err != nil { @@ -3339,6 +3393,31 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr return out } +var remoteModelWithOmitemptyImplementors = []string{"RemoteModelWithOmitempty"} + +func (ec *executionContext) _RemoteModelWithOmitempty(ctx context.Context, sel ast.SelectionSet, obj *testomitempty.RemoteModelWithOmitempty) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, remoteModelWithOmitemptyImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("RemoteModelWithOmitempty") + case "newDesc": + + out.Values[i] = ec._RemoteModelWithOmitempty_newDesc(ctx, field, obj) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var userImplementors = []string{"User"} func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *remote_api.User) graphql.Marshaler { @@ -4405,6 +4484,16 @@ func (ec *executionContext) marshalOMap2ᚕmap(ctx context.Context, sel ast.Sele return ret } +func (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + return res +} + func (ec *executionContext) unmarshalOString2ᚕᚖstring(ctx context.Context, v interface{}) ([]*string, error) { if v == nil { return nil, nil diff --git a/integration/gqlgen.yml b/integration/gqlgen.yml index e3ca845f942..7ecb5b84ce7 100644 --- a/integration/gqlgen.yml +++ b/integration/gqlgen.yml @@ -1,6 +1,7 @@ schema: - "schema.graphql" - "user.graphql" + - "testomitempty.graphql" exec: filename: generated.go @@ -10,6 +11,11 @@ resolver: filename: resolver.go type: Resolver +struct_tag: json + +autobind: + - "github.com/99designs/gqlgen/integration/testomitempty" + models: Element: model: github.com/99designs/gqlgen/integration/models-go.Element diff --git a/integration/schema-expected.graphql b/integration/schema-expected.graphql index 64877ae767d..48d4252addf 100644 --- a/integration/schema-expected.graphql +++ b/integration/schema-expected.graphql @@ -46,6 +46,10 @@ type Query { viewer: Viewer } +type RemoteModelWithOmitempty { + newDesc: String +} + type User { likes: [String!]! name: String! diff --git a/integration/testomitempty.graphql b/integration/testomitempty.graphql new file mode 100644 index 00000000000..7a9285ae9d2 --- /dev/null +++ b/integration/testomitempty.graphql @@ -0,0 +1,3 @@ +type RemoteModelWithOmitempty { + newDesc: String +} diff --git a/integration/testomitempty/testmodel.go b/integration/testomitempty/testmodel.go new file mode 100644 index 00000000000..a7121659ddd --- /dev/null +++ b/integration/testomitempty/testmodel.go @@ -0,0 +1,5 @@ +package testomitempty + +type RemoteModelWithOmitempty struct { + Description string `json:"newDesc,omitempty"` +}