diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 5344d9cf..f6ca18c3 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -34,6 +34,7 @@ When releasing a new version: - The `omitempty` option now works correctly for struct- and map-typed variables, matching `encoding/json`, which is to say it never omits structs, and omits empty maps. (#43) - Generated type-names now abbreviate across multiple components; for example if the path to a type is `(MyOperation, Outer, Outer, Inner, OuterInner)`, it will again be called `MyOperationOuterInner`. (This regressed in a pre-v0.1.0 refactor.) (#109) +- Previously, interface fields with `# @genqlient(pointer: true)` would be unmarshaled to `(*MyInterface)(*)`, i.e. a pointer to the untyped-nil of the interface type. Now they are unmarshaled as `(*MyInterface)()`, i.e. a nil pointer of the pointer-to-interface type, as you would expect. ## v0.1.0 diff --git a/generate/marshal.go.tmpl b/generate/marshal.go.tmpl index 10d595e7..0f31c3d0 100644 --- a/generate/marshal.go.tmpl +++ b/generate/marshal.go.tmpl @@ -30,9 +30,15 @@ func (v *{{.GoName}}) MarshalJSON() ([]byte, error) { for i, src := range src { dst := &(*dst)[i] {{end -}} + {{/* src now has type ; dst is json.RawMessage */ -}} + {{if $field.GoType.IsPointer -}} + {{/* If you passed a pointer, and it's nil, don't call the + marshaler. This matches json.Marshal's behavior. */ -}} + if src != nil { + {{end -}} var err error *dst, err = {{$field.Marshaler $.Generator}}( - {{/* src is a pointer to the struct-field (or field-element, etc.). + {{/* src is the struct-field (or field-element, etc.). We want to pass a pointer to the type you specified, so if there's a pointer on the field that's exactly what we want, and if not we need to take the address. */ -}} @@ -41,6 +47,9 @@ func (v *{{.GoName}}) MarshalJSON() ([]byte, error) { return nil, fmt.Errorf( "Unable to marshal {{$.GoName}}.{{$field.GoName}}: %w", err) } + {{if $field.GoType.IsPointer -}} + }{{/* end if src != nil */}} + {{end -}} {{range $i := intRange $field.GoType.SliceDepth -}} } {{end -}} diff --git a/generate/testdata/snapshots/TestGenerate-ComplexInlineFragments.graphql-ComplexInlineFragments.graphql.go b/generate/testdata/snapshots/TestGenerate-ComplexInlineFragments.graphql-ComplexInlineFragments.graphql.go index a5df8755..5e4d035e 100644 --- a/generate/testdata/snapshots/TestGenerate-ComplexInlineFragments.graphql-ComplexInlineFragments.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-ComplexInlineFragments.graphql-ComplexInlineFragments.graphql.go @@ -206,11 +206,13 @@ func (v *ComplexInlineFragmentsNestedStuffTopic) UnmarshalJSON(b []byte) error { len(src)) for i, src := range src { dst := &(*dst)[i] - err = __unmarshalComplexInlineFragmentsNestedStuffTopicChildrenContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal ComplexInlineFragmentsNestedStuffTopic.Children: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalComplexInlineFragmentsNestedStuffTopicChildrenContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal ComplexInlineFragmentsNestedStuffTopic.Children: %w", err) + } } } } @@ -257,11 +259,13 @@ func (v *ComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParen len(src)) for i, src := range src { dst := &(*dst)[i] - err = __unmarshalComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParentTopicChildrenContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal ComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParentTopic.Children: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParentTopicChildrenContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal ComplexInlineFragmentsNestedStuffTopicChildrenArticleParentContentParentTopic.Children: %w", err) + } } } } @@ -819,44 +823,52 @@ func (v *ComplexInlineFragmentsResponse) UnmarshalJSON(b []byte) error { { dst := &v.RandomItem src := firstPass.RandomItem - err = __unmarshalComplexInlineFragmentsRandomItemContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal ComplexInlineFragmentsResponse.RandomItem: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalComplexInlineFragmentsRandomItemContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal ComplexInlineFragmentsResponse.RandomItem: %w", err) + } } } { dst := &v.RepeatedStuff src := firstPass.RepeatedStuff - err = __unmarshalComplexInlineFragmentsRepeatedStuffContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal ComplexInlineFragmentsResponse.RepeatedStuff: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalComplexInlineFragmentsRepeatedStuffContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal ComplexInlineFragmentsResponse.RepeatedStuff: %w", err) + } } } { dst := &v.ConflictingStuff src := firstPass.ConflictingStuff - err = __unmarshalComplexInlineFragmentsConflictingStuffContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal ComplexInlineFragmentsResponse.ConflictingStuff: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalComplexInlineFragmentsConflictingStuffContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal ComplexInlineFragmentsResponse.ConflictingStuff: %w", err) + } } } { dst := &v.NestedStuff src := firstPass.NestedStuff - err = __unmarshalComplexInlineFragmentsNestedStuffContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal ComplexInlineFragmentsResponse.NestedStuff: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalComplexInlineFragmentsNestedStuffContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal ComplexInlineFragmentsResponse.NestedStuff: %w", err) + } } } return nil diff --git a/generate/testdata/snapshots/TestGenerate-ComplexNamedFragments.graphql-ComplexNamedFragments.graphql.go b/generate/testdata/snapshots/TestGenerate-ComplexNamedFragments.graphql-ComplexNamedFragments.graphql.go index ecd1254e..df90dc50 100644 --- a/generate/testdata/snapshots/TestGenerate-ComplexNamedFragments.graphql-ComplexNamedFragments.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-ComplexNamedFragments.graphql-ComplexNamedFragments.graphql.go @@ -173,33 +173,39 @@ func (v *InnerQueryFragment) UnmarshalJSON(b []byte) error { { dst := &v.RandomItem src := firstPass.RandomItem - err = __unmarshalInnerQueryFragmentRandomItemContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal InnerQueryFragment.RandomItem: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalInnerQueryFragmentRandomItemContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal InnerQueryFragment.RandomItem: %w", err) + } } } { dst := &v.RandomLeaf src := firstPass.RandomLeaf - err = __unmarshalInnerQueryFragmentRandomLeafLeafContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal InnerQueryFragment.RandomLeaf: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalInnerQueryFragmentRandomLeafLeafContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal InnerQueryFragment.RandomLeaf: %w", err) + } } } { dst := &v.OtherLeaf src := firstPass.OtherLeaf - err = __unmarshalInnerQueryFragmentOtherLeafLeafContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal InnerQueryFragment.OtherLeaf: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalInnerQueryFragmentOtherLeafLeafContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal InnerQueryFragment.OtherLeaf: %w", err) + } } } return nil @@ -703,11 +709,13 @@ func (v *MoreVideoFieldsParentTopic) UnmarshalJSON(b []byte) error { len(src)) for i, src := range src { dst := &(*dst)[i] - err = __unmarshalMoreVideoFieldsParentTopicChildrenContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal MoreVideoFieldsParentTopic.Children: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalMoreVideoFieldsParentTopicChildrenContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal MoreVideoFieldsParentTopic.Children: %w", err) + } } } } diff --git a/generate/testdata/snapshots/TestGenerate-CustomMarshal.graphql-CustomMarshal.graphql.go b/generate/testdata/snapshots/TestGenerate-CustomMarshal.graphql-CustomMarshal.graphql.go index 00c711de..bd7b1407 100644 --- a/generate/testdata/snapshots/TestGenerate-CustomMarshal.graphql-CustomMarshal.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-CustomMarshal.graphql-CustomMarshal.graphql.go @@ -49,11 +49,13 @@ func (v *CustomMarshalUsersBornOnUser) UnmarshalJSON(b []byte) error { { dst := &v.Birthdate src := firstPass.Birthdate - err = testutil.UnmarshalDate( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal CustomMarshalUsersBornOnUser.Birthdate: %w", err) + if len(src) != 0 && string(src) != "null" { + err = testutil.UnmarshalDate( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal CustomMarshalUsersBornOnUser.Birthdate: %w", err) + } } } return nil diff --git a/generate/testdata/snapshots/TestGenerate-CustomMarshalSlice.graphql-CustomMarshalSlice.graphql.go b/generate/testdata/snapshots/TestGenerate-CustomMarshalSlice.graphql-CustomMarshalSlice.graphql.go index d7462d3e..dcc2c9e2 100644 --- a/generate/testdata/snapshots/TestGenerate-CustomMarshalSlice.graphql-CustomMarshalSlice.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-CustomMarshalSlice.graphql-CustomMarshalSlice.graphql.go @@ -82,12 +82,14 @@ func (v *__CustomMarshalSliceInput) MarshalJSON() ([]byte, error) { len(src)) for i, src := range src { dst := &(*dst)[i] - var err error - *dst, err = testutil.MarshalDate( - src) - if err != nil { - return nil, fmt.Errorf( - "Unable to marshal __CustomMarshalSliceInput.Datesssp: %w", err) + if src != nil { + var err error + *dst, err = testutil.MarshalDate( + src) + if err != nil { + return nil, fmt.Errorf( + "Unable to marshal __CustomMarshalSliceInput.Datesssp: %w", err) + } } } } diff --git a/generate/testdata/snapshots/TestGenerate-InterfaceListField.graphql-InterfaceListField.graphql.go b/generate/testdata/snapshots/TestGenerate-InterfaceListField.graphql-InterfaceListField.graphql.go index 351abaea..11f475bb 100644 --- a/generate/testdata/snapshots/TestGenerate-InterfaceListField.graphql-InterfaceListField.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-InterfaceListField.graphql-InterfaceListField.graphql.go @@ -50,11 +50,13 @@ func (v *InterfaceListFieldRootTopic) UnmarshalJSON(b []byte) error { len(src)) for i, src := range src { dst := &(*dst)[i] - err = __unmarshalInterfaceListFieldRootTopicChildrenContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal InterfaceListFieldRootTopic.Children: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalInterfaceListFieldRootTopicChildrenContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal InterfaceListFieldRootTopic.Children: %w", err) + } } } } @@ -209,11 +211,13 @@ func (v *InterfaceListFieldWithPointerTopic) UnmarshalJSON(b []byte) error { len(src)) for i, src := range src { dst := &(*dst)[i] - err = __unmarshalInterfaceListFieldWithPointerTopicChildrenContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal InterfaceListFieldWithPointerTopic.Children: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalInterfaceListFieldWithPointerTopicChildrenContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal InterfaceListFieldWithPointerTopic.Children: %w", err) + } } } } diff --git a/generate/testdata/snapshots/TestGenerate-InterfaceListOfListsOfListsField.graphql-InterfaceListOfListsOfListsField.graphql.go b/generate/testdata/snapshots/TestGenerate-InterfaceListOfListsOfListsField.graphql-InterfaceListOfListsOfListsField.graphql.go index 9cc43b13..f5b5092b 100644 --- a/generate/testdata/snapshots/TestGenerate-InterfaceListOfListsOfListsField.graphql-InterfaceListOfListsOfListsField.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-InterfaceListOfListsOfListsField.graphql-InterfaceListOfListsOfListsField.graphql.go @@ -185,11 +185,13 @@ func (v *InterfaceListOfListOfListsFieldResponse) UnmarshalJSON(b []byte) error len(src)) for i, src := range src { dst := &(*dst)[i] - err = __unmarshalInterfaceListOfListOfListsFieldListOfListsOfListsOfContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal InterfaceListOfListOfListsFieldResponse.ListOfListsOfListsOfContent: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalInterfaceListOfListOfListsFieldListOfListsOfListsOfContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal InterfaceListOfListOfListsFieldResponse.ListOfListsOfListsOfContent: %w", err) + } } } } @@ -214,12 +216,14 @@ func (v *InterfaceListOfListOfListsFieldResponse) UnmarshalJSON(b []byte) error len(src)) for i, src := range src { dst := &(*dst)[i] - *dst = new(InterfaceListOfListOfListsFieldWithPointerContent) - err = __unmarshalInterfaceListOfListOfListsFieldWithPointerContent( - src, *dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal InterfaceListOfListOfListsFieldResponse.WithPointer: %w", err) + if len(src) != 0 && string(src) != "null" { + *dst = new(InterfaceListOfListOfListsFieldWithPointerContent) + err = __unmarshalInterfaceListOfListOfListsFieldWithPointerContent( + src, *dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal InterfaceListOfListOfListsFieldResponse.WithPointer: %w", err) + } } } } diff --git a/generate/testdata/snapshots/TestGenerate-InterfaceNesting.graphql-InterfaceNesting.graphql.go b/generate/testdata/snapshots/TestGenerate-InterfaceNesting.graphql-InterfaceNesting.graphql.go index a493d8c4..5a3f66e9 100644 --- a/generate/testdata/snapshots/TestGenerate-InterfaceNesting.graphql-InterfaceNesting.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-InterfaceNesting.graphql-InterfaceNesting.graphql.go @@ -48,11 +48,13 @@ func (v *InterfaceNestingRootTopic) UnmarshalJSON(b []byte) error { len(src)) for i, src := range src { dst := &(*dst)[i] - err = __unmarshalInterfaceNestingRootTopicChildrenContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal InterfaceNestingRootTopic.Children: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalInterfaceNestingRootTopicChildrenContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal InterfaceNestingRootTopic.Children: %w", err) + } } } } @@ -196,11 +198,13 @@ func (v *InterfaceNestingRootTopicChildrenContentParentTopic) UnmarshalJSON(b [] len(src)) for i, src := range src { dst := &(*dst)[i] - err = __unmarshalInterfaceNestingRootTopicChildrenContentParentTopicChildrenContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal InterfaceNestingRootTopicChildrenContentParentTopic.Children: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalInterfaceNestingRootTopicChildrenContentParentTopicChildrenContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal InterfaceNestingRootTopicChildrenContentParentTopic.Children: %w", err) + } } } } diff --git a/generate/testdata/snapshots/TestGenerate-InterfaceNoFragments.graphql-InterfaceNoFragments.graphql.go b/generate/testdata/snapshots/TestGenerate-InterfaceNoFragments.graphql-InterfaceNoFragments.graphql.go index b50b156c..74b72c5f 100644 --- a/generate/testdata/snapshots/TestGenerate-InterfaceNoFragments.graphql-InterfaceNoFragments.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-InterfaceNoFragments.graphql-InterfaceNoFragments.graphql.go @@ -275,34 +275,40 @@ func (v *InterfaceNoFragmentsQueryResponse) UnmarshalJSON(b []byte) error { { dst := &v.RandomItem src := firstPass.RandomItem - err = __unmarshalInterfaceNoFragmentsQueryRandomItemContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal InterfaceNoFragmentsQueryResponse.RandomItem: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalInterfaceNoFragmentsQueryRandomItemContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal InterfaceNoFragmentsQueryResponse.RandomItem: %w", err) + } } } { dst := &v.RandomItemWithTypeName src := firstPass.RandomItemWithTypeName - err = __unmarshalInterfaceNoFragmentsQueryRandomItemWithTypeNameContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal InterfaceNoFragmentsQueryResponse.RandomItemWithTypeName: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalInterfaceNoFragmentsQueryRandomItemWithTypeNameContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal InterfaceNoFragmentsQueryResponse.RandomItemWithTypeName: %w", err) + } } } { dst := &v.WithPointer src := firstPass.WithPointer - *dst = new(InterfaceNoFragmentsQueryWithPointerContent) - err = __unmarshalInterfaceNoFragmentsQueryWithPointerContent( - src, *dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal InterfaceNoFragmentsQueryResponse.WithPointer: %w", err) + if len(src) != 0 && string(src) != "null" { + *dst = new(InterfaceNoFragmentsQueryWithPointerContent) + err = __unmarshalInterfaceNoFragmentsQueryWithPointerContent( + src, *dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal InterfaceNoFragmentsQueryResponse.WithPointer: %w", err) + } } } return nil diff --git a/generate/testdata/snapshots/TestGenerate-MultipleDirectives.graphql-MultipleDirectives.graphql.go b/generate/testdata/snapshots/TestGenerate-MultipleDirectives.graphql-MultipleDirectives.graphql.go index d17af648..560cb610 100644 --- a/generate/testdata/snapshots/TestGenerate-MultipleDirectives.graphql-MultipleDirectives.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-MultipleDirectives.graphql-MultipleDirectives.graphql.go @@ -40,12 +40,14 @@ func (v *MyInput) MarshalJSON() ([]byte, error) { dst := &fullObject.Birthdate src := v.Birthdate - var err error - *dst, err = testutil.MarshalDate( - src) - if err != nil { - return nil, fmt.Errorf( - "Unable to marshal MyInput.Birthdate: %w", err) + if src != nil { + var err error + *dst, err = testutil.MarshalDate( + src) + if err != nil { + return nil, fmt.Errorf( + "Unable to marshal MyInput.Birthdate: %w", err) + } } } @@ -127,12 +129,14 @@ func (v *UserQueryInput) MarshalJSON() ([]byte, error) { dst := &fullObject.Birthdate src := v.Birthdate - var err error - *dst, err = testutil.MarshalDate( - src) - if err != nil { - return nil, fmt.Errorf( - "Unable to marshal UserQueryInput.Birthdate: %w", err) + if src != nil { + var err error + *dst, err = testutil.MarshalDate( + src) + if err != nil { + return nil, fmt.Errorf( + "Unable to marshal UserQueryInput.Birthdate: %w", err) + } } } diff --git a/generate/testdata/snapshots/TestGenerate-Pointers.graphql-Pointers.graphql.go b/generate/testdata/snapshots/TestGenerate-Pointers.graphql-Pointers.graphql.go index 6b6a6f9a..0c0cdaea 100644 --- a/generate/testdata/snapshots/TestGenerate-Pointers.graphql-Pointers.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-Pointers.graphql-Pointers.graphql.go @@ -95,12 +95,14 @@ func (v *UserQueryInput) MarshalJSON() ([]byte, error) { dst := &fullObject.Birthdate src := v.Birthdate - var err error - *dst, err = testutil.MarshalDate( - src) - if err != nil { - return nil, fmt.Errorf( - "Unable to marshal UserQueryInput.Birthdate: %w", err) + if src != nil { + var err error + *dst, err = testutil.MarshalDate( + src) + if err != nil { + return nil, fmt.Errorf( + "Unable to marshal UserQueryInput.Birthdate: %w", err) + } } } diff --git a/generate/testdata/snapshots/TestGenerate-SimpleInlineFragment.graphql-SimpleInlineFragment.graphql.go b/generate/testdata/snapshots/TestGenerate-SimpleInlineFragment.graphql-SimpleInlineFragment.graphql.go index 74f4cfd2..673f55ed 100644 --- a/generate/testdata/snapshots/TestGenerate-SimpleInlineFragment.graphql-SimpleInlineFragment.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-SimpleInlineFragment.graphql-SimpleInlineFragment.graphql.go @@ -152,11 +152,13 @@ func (v *SimpleInlineFragmentResponse) UnmarshalJSON(b []byte) error { { dst := &v.RandomItem src := firstPass.RandomItem - err = __unmarshalSimpleInlineFragmentRandomItemContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal SimpleInlineFragmentResponse.RandomItem: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalSimpleInlineFragmentRandomItemContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal SimpleInlineFragmentResponse.RandomItem: %w", err) + } } } return nil diff --git a/generate/testdata/snapshots/TestGenerate-SimpleNamedFragment.graphql-SimpleNamedFragment.graphql.go b/generate/testdata/snapshots/TestGenerate-SimpleNamedFragment.graphql-SimpleNamedFragment.graphql.go index f8e15838..b8d4de3f 100644 --- a/generate/testdata/snapshots/TestGenerate-SimpleNamedFragment.graphql-SimpleNamedFragment.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-SimpleNamedFragment.graphql-SimpleNamedFragment.graphql.go @@ -269,22 +269,26 @@ func (v *SimpleNamedFragmentResponse) UnmarshalJSON(b []byte) error { { dst := &v.RandomItem src := firstPass.RandomItem - err = __unmarshalSimpleNamedFragmentRandomItemContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal SimpleNamedFragmentResponse.RandomItem: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalSimpleNamedFragmentRandomItemContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal SimpleNamedFragmentResponse.RandomItem: %w", err) + } } } { dst := &v.RandomLeaf src := firstPass.RandomLeaf - err = __unmarshalSimpleNamedFragmentRandomLeafLeafContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal SimpleNamedFragmentResponse.RandomLeaf: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalSimpleNamedFragmentRandomLeafLeafContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal SimpleNamedFragmentResponse.RandomLeaf: %w", err) + } } } return nil diff --git a/generate/testdata/snapshots/TestGenerate-StructOption.graphql-StructOption.graphql.go b/generate/testdata/snapshots/TestGenerate-StructOption.graphql-StructOption.graphql.go index 7c6b6315..29d8b47c 100644 --- a/generate/testdata/snapshots/TestGenerate-StructOption.graphql-StructOption.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-StructOption.graphql-StructOption.graphql.go @@ -86,11 +86,13 @@ func (v *StructOptionRootTopicChildrenContentParentTopic) UnmarshalJSON(b []byte len(src)) for i, src := range src { dst := &(*dst)[i] - err = __unmarshalStructOptionRootTopicChildrenContentParentTopicInterfaceChildrenContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal StructOptionRootTopicChildrenContentParentTopic.InterfaceChildren: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalStructOptionRootTopicChildrenContentParentTopicInterfaceChildrenContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal StructOptionRootTopicChildrenContentParentTopic.InterfaceChildren: %w", err) + } } } } diff --git a/generate/testdata/snapshots/TestGenerate-TypeNames.graphql-TypeNames.graphql.go b/generate/testdata/snapshots/TestGenerate-TypeNames.graphql-TypeNames.graphql.go index fabe85fd..cf8687bd 100644 --- a/generate/testdata/snapshots/TestGenerate-TypeNames.graphql-TypeNames.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-TypeNames.graphql-TypeNames.graphql.go @@ -153,11 +153,13 @@ func (v *Resp) UnmarshalJSON(b []byte) error { { dst := &v.RandomItem src := firstPass.RandomItem - err = __unmarshalItem( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal Resp.RandomItem: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalItem( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal Resp.RandomItem: %w", err) + } } } return nil diff --git a/generate/testdata/snapshots/TestGenerate-UnionNoFragments.graphql-UnionNoFragments.graphql.go b/generate/testdata/snapshots/TestGenerate-UnionNoFragments.graphql-UnionNoFragments.graphql.go index 657fe483..8f6d50ed 100644 --- a/generate/testdata/snapshots/TestGenerate-UnionNoFragments.graphql-UnionNoFragments.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-UnionNoFragments.graphql-UnionNoFragments.graphql.go @@ -100,11 +100,13 @@ func (v *UnionNoFragmentsQueryResponse) UnmarshalJSON(b []byte) error { { dst := &v.RandomLeaf src := firstPass.RandomLeaf - err = __unmarshalUnionNoFragmentsQueryRandomLeafLeafContent( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal UnionNoFragmentsQueryResponse.RandomLeaf: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalUnionNoFragmentsQueryRandomLeafLeafContent( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal UnionNoFragmentsQueryResponse.RandomLeaf: %w", err) + } } } return nil diff --git a/generate/unmarshal.go.tmpl b/generate/unmarshal.go.tmpl index 14a08b92..db0942b7 100644 --- a/generate/unmarshal.go.tmpl +++ b/generate/unmarshal.go.tmpl @@ -102,17 +102,24 @@ func (v *{{.GoName}}) UnmarshalJSON(b []byte) error { for i, src := range src { dst := &(*dst)[i] {{end -}} - {{if $field.GoType.IsPointer -}} - {{/* In this case, the parent for loop did `make([]*MyType, ...)` and - we have a pointer into that list. But we actually still need to - initialize the *elements* of the list. */ -}} - *dst = new({{$field.GoType.Unwrap.Reference}}) - {{end -}} - err = {{$field.Unmarshaler $.Generator}}( - src, {{if $field.GoType.IsPointer}}*{{end}}dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal {{$.GoName}}.{{$field.GoName}}: %w", err) + {{/* dst now has type *; dst is json.RawMessage */ -}} + {{/* If the field is null in the input, skip calling unmarshaler. + (This matches json.Unmarshal.) If the field is missing entirely + from the input, we will have an uninitialized json.RawMessage; + handle that likewise. */ -}} + if len(src) != 0 && string(src) != "null" { + {{if $field.GoType.IsPointer -}} + {{/* In this case, the parent for loop did `make([]*MyType, ...)` + and we have a pointer into that list. But we actually still + need to initialize the *elements* of the list. */ -}} + *dst = new({{$field.GoType.Unwrap.Reference}}) + {{end -}} + err = {{$field.Unmarshaler $.Generator}}( + src, {{if $field.GoType.IsPointer}}*{{end}}dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal {{$.GoName}}.{{$field.GoName}}: %w", err) + } } {{range $i := intRange $field.GoType.SliceDepth -}} } diff --git a/internal/integration/generated.go b/internal/integration/generated.go index 40ab3a14..d904fa7c 100644 --- a/internal/integration/generated.go +++ b/internal/integration/generated.go @@ -40,11 +40,13 @@ func (v *AnimalFields) UnmarshalJSON(b []byte) error { { dst := &v.Owner src := firstPass.Owner - err = __unmarshalAnimalFieldsOwnerBeing( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal AnimalFields.Owner: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalAnimalFieldsOwnerBeing( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal AnimalFields.Owner: %w", err) + } } } return nil @@ -314,6 +316,39 @@ func (v *__queryWithCustomMarshalInput) MarshalJSON() ([]byte, error) { return json.Marshal(&fullObject) } +// __queryWithCustomMarshalOptionalInput is used internally by genqlient +type __queryWithCustomMarshalOptionalInput struct { + Date *time.Time `json:"-"` + Id *string `json:"id"` +} + +func (v *__queryWithCustomMarshalOptionalInput) MarshalJSON() ([]byte, error) { + + var fullObject struct { + *__queryWithCustomMarshalOptionalInput + Date json.RawMessage `json:"date"` + graphql.NoMarshalJSON + } + fullObject.__queryWithCustomMarshalOptionalInput = v + + { + + dst := &fullObject.Date + src := v.Date + if src != nil { + var err error + *dst, err = testutil.MarshalDate( + src) + if err != nil { + return nil, fmt.Errorf( + "Unable to marshal __queryWithCustomMarshalOptionalInput.Date: %w", err) + } + } + } + + return json.Marshal(&fullObject) +} + // __queryWithCustomMarshalSliceInput is used internally by genqlient type __queryWithCustomMarshalSliceInput struct { Dates []time.Time `json:"-"` @@ -396,6 +431,51 @@ type failingQueryResponse struct { Me failingQueryMeUser `json:"me"` } +// queryWithCustomMarshalOptionalResponse is returned by queryWithCustomMarshalOptional on success. +type queryWithCustomMarshalOptionalResponse struct { + UserSearch []queryWithCustomMarshalOptionalUserSearchUser `json:"userSearch"` +} + +// queryWithCustomMarshalOptionalUserSearchUser includes the requested fields of the GraphQL type User. +type queryWithCustomMarshalOptionalUserSearchUser struct { + Id string `json:"id"` + Name string `json:"name"` + Birthdate time.Time `json:"-"` +} + +func (v *queryWithCustomMarshalOptionalUserSearchUser) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *queryWithCustomMarshalOptionalUserSearchUser + Birthdate json.RawMessage `json:"birthdate"` + graphql.NoUnmarshalJSON + } + firstPass.queryWithCustomMarshalOptionalUserSearchUser = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.Birthdate + src := firstPass.Birthdate + if len(src) != 0 && string(src) != "null" { + err = testutil.UnmarshalDate( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal queryWithCustomMarshalOptionalUserSearchUser.Birthdate: %w", err) + } + } + } + return nil +} + // queryWithCustomMarshalResponse is returned by queryWithCustomMarshal on success. type queryWithCustomMarshalResponse struct { UsersBornOn []queryWithCustomMarshalUsersBornOnUser `json:"usersBornOn"` @@ -434,11 +514,13 @@ func (v *queryWithCustomMarshalSliceUsersBornOnDatesUser) UnmarshalJSON(b []byte { dst := &v.Birthdate src := firstPass.Birthdate - err = testutil.UnmarshalDate( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal queryWithCustomMarshalSliceUsersBornOnDatesUser.Birthdate: %w", err) + if len(src) != 0 && string(src) != "null" { + err = testutil.UnmarshalDate( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal queryWithCustomMarshalSliceUsersBornOnDatesUser.Birthdate: %w", err) + } } } return nil @@ -472,11 +554,13 @@ func (v *queryWithCustomMarshalUsersBornOnUser) UnmarshalJSON(b []byte) error { { dst := &v.Birthdate src := firstPass.Birthdate - err = testutil.UnmarshalDate( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal queryWithCustomMarshalUsersBornOnUser.Birthdate: %w", err) + if len(src) != 0 && string(src) != "null" { + err = testutil.UnmarshalDate( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal queryWithCustomMarshalUsersBornOnUser.Birthdate: %w", err) + } } } return nil @@ -513,11 +597,13 @@ func (v *queryWithFragmentsBeingsAnimal) UnmarshalJSON(b []byte) error { { dst := &v.Owner src := firstPass.Owner - err = __unmarshalqueryWithFragmentsBeingsAnimalOwnerBeing( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal queryWithFragmentsBeingsAnimal.Owner: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalqueryWithFragmentsBeingsAnimalOwnerBeing( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal queryWithFragmentsBeingsAnimal.Owner: %w", err) + } } } return nil @@ -722,11 +808,13 @@ func (v *queryWithFragmentsResponse) UnmarshalJSON(b []byte) error { len(src)) for i, src := range src { dst := &(*dst)[i] - err = __unmarshalqueryWithFragmentsBeingsBeing( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal queryWithFragmentsResponse.Beings: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalqueryWithFragmentsBeingsBeing( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal queryWithFragmentsResponse.Beings: %w", err) + } } } } @@ -846,11 +934,13 @@ func (v *queryWithInterfaceListFieldResponse) UnmarshalJSON(b []byte) error { len(src)) for i, src := range src { dst := &(*dst)[i] - err = __unmarshalqueryWithInterfaceListFieldBeingsBeing( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal queryWithInterfaceListFieldResponse.Beings: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalqueryWithInterfaceListFieldBeingsBeing( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal queryWithInterfaceListFieldResponse.Beings: %w", err) + } } } } @@ -970,12 +1060,14 @@ func (v *queryWithInterfaceListPointerFieldResponse) UnmarshalJSON(b []byte) err len(src)) for i, src := range src { dst := &(*dst)[i] - *dst = new(queryWithInterfaceListPointerFieldBeingsBeing) - err = __unmarshalqueryWithInterfaceListPointerFieldBeingsBeing( - src, *dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal queryWithInterfaceListPointerFieldResponse.Beings: %w", err) + if len(src) != 0 && string(src) != "null" { + *dst = new(queryWithInterfaceListPointerFieldBeingsBeing) + err = __unmarshalqueryWithInterfaceListPointerFieldBeingsBeing( + src, *dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal queryWithInterfaceListPointerFieldResponse.Beings: %w", err) + } } } } @@ -1097,11 +1189,13 @@ func (v *queryWithInterfaceNoFragmentsResponse) UnmarshalJSON(b []byte) error { { dst := &v.Being src := firstPass.Being - err = __unmarshalqueryWithInterfaceNoFragmentsBeing( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal queryWithInterfaceNoFragmentsResponse.Being: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalqueryWithInterfaceNoFragmentsBeing( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal queryWithInterfaceNoFragmentsResponse.Being: %w", err) + } } } return nil @@ -1262,11 +1356,13 @@ func (v *queryWithNamedFragmentsResponse) UnmarshalJSON(b []byte) error { len(src)) for i, src := range src { dst := &(*dst)[i] - err = __unmarshalqueryWithNamedFragmentsBeingsBeing( - src, dst) - if err != nil { - return fmt.Errorf( - "Unable to unmarshal queryWithNamedFragmentsResponse.Beings: %w", err) + if len(src) != 0 && string(src) != "null" { + err = __unmarshalqueryWithNamedFragmentsBeingsBeing( + src, dst) + if err != nil { + return fmt.Errorf( + "Unable to unmarshal queryWithNamedFragmentsResponse.Beings: %w", err) + } } } } @@ -1474,6 +1570,37 @@ query queryWithCustomMarshalSlice ($dates: [Date!]!) { return &retval, err } +func queryWithCustomMarshalOptional( + ctx context.Context, + client graphql.Client, + date *time.Time, + id *string, +) (*queryWithCustomMarshalOptionalResponse, error) { + __input := __queryWithCustomMarshalOptionalInput{ + Date: date, + Id: id, + } + var err error + + var retval queryWithCustomMarshalOptionalResponse + err = client.MakeRequest( + ctx, + "queryWithCustomMarshalOptional", + ` +query queryWithCustomMarshalOptional ($date: Date, $id: ID) { + userSearch(birthdate: $date, id: $id) { + id + name + birthdate + } +} +`, + &retval, + &__input, + ) + return &retval, err +} + func queryWithInterfaceNoFragments( ctx context.Context, client graphql.Client, diff --git a/internal/integration/integration_test.go b/internal/integration/integration_test.go index 41b1ddef..132582a5 100644 --- a/internal/integration/integration_test.go +++ b/internal/integration/integration_test.go @@ -175,6 +175,44 @@ func TestCustomMarshalSlice(t *testing.T) { assert.Len(t, resp.UsersBornOnDates, 0) } +func TestCustomMarshalOptional(t *testing.T) { + _ = `# @genqlient + query queryWithCustomMarshalOptional( + # @genqlient(pointer: true) + $date: Date, + # @genqlient(pointer: true) + $id: ID, + ) { + userSearch(birthdate: $date, id: $id) { id name birthdate } + }` + + ctx := context.Background() + server := server.RunServer() + defer server.Close() + client := graphql.NewClient(server.URL, http.DefaultClient) + + date := time.Date(2025, time.January, 1, 12, 34, 56, 789, time.UTC) + resp, err := queryWithCustomMarshalOptional(ctx, client, &date, nil) + require.NoError(t, err) + + assert.Len(t, resp.UserSearch, 1) + user := resp.UserSearch[0] + assert.Equal(t, "1", user.Id) + assert.Equal(t, "Yours Truly", user.Name) + assert.Equal(t, + time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC), + user.Birthdate) + + id := "2" + resp, err = queryWithCustomMarshalOptional(ctx, client, nil, &id) + require.NoError(t, err) + assert.Len(t, resp.UserSearch, 1) + user = resp.UserSearch[0] + assert.Equal(t, "2", user.Id) + assert.Equal(t, "Raven", user.Name) + assert.Zero(t, user.Birthdate) +} + func TestInterfaceNoFragments(t *testing.T) { _ = `# @genqlient query queryWithInterfaceNoFragments($id: ID!) { @@ -322,7 +360,7 @@ func TestInterfaceListPointerField(t *testing.T) { assert.Equal(t, "3", animal.Id) assert.Equal(t, "Fido", animal.Name) - assert.Nil(t, *resp.Beings[2]) + assert.Nil(t, resp.Beings[2]) } func TestFragments(t *testing.T) { diff --git a/internal/integration/schema.graphql b/internal/integration/schema.graphql index e7c59420..a9e581c1 100644 --- a/internal/integration/schema.graphql +++ b/internal/integration/schema.graphql @@ -8,6 +8,7 @@ type Query { lotteryWinner(number: Int!): Lucky usersBornOn(date: Date!): [User!]! usersBornOnDates(dates: [Date!]!): [User!]! + userSearch(birthdate: Date, id: ID): [User] fail: Boolean } diff --git a/internal/integration/server/gqlgen_exec.go b/internal/integration/server/gqlgen_exec.go index 7c7e8e30..6a4cf241 100644 --- a/internal/integration/server/gqlgen_exec.go +++ b/internal/integration/server/gqlgen_exec.go @@ -65,6 +65,7 @@ type ComplexityRoot struct { LotteryWinner func(childComplexity int, number int) int Me func(childComplexity int) int User func(childComplexity int, id *string) int + UserSearch func(childComplexity int, birthdate *string, id *string) int UsersBornOn func(childComplexity int, date string) int UsersBornOnDates func(childComplexity int, dates []string) int } @@ -86,6 +87,7 @@ type QueryResolver interface { LotteryWinner(ctx context.Context, number int) (Lucky, error) UsersBornOn(ctx context.Context, date string) ([]*User, error) UsersBornOnDates(ctx context.Context, dates []string) ([]*User, error) + UserSearch(ctx context.Context, birthdate *string, id *string) ([]*User, error) Fail(ctx context.Context) (*bool, error) } @@ -215,6 +217,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.User(childComplexity, args["id"].(*string)), true + case "Query.userSearch": + if e.complexity.Query.UserSearch == nil { + break + } + + args, err := ec.field_Query_userSearch_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.UserSearch(childComplexity, args["birthdate"].(*string), args["id"].(*string)), true + case "Query.usersBornOn": if e.complexity.Query.UsersBornOn == nil { break @@ -334,6 +348,7 @@ type Query { lotteryWinner(number: Int!): Lucky usersBornOn(date: Date!): [User!]! usersBornOnDates(dates: [Date!]!): [User!]! + userSearch(birthdate: Date, id: ID): [User] fail: Boolean } @@ -438,6 +453,30 @@ func (ec *executionContext) field_Query_lotteryWinner_args(ctx context.Context, return args, nil } +func (ec *executionContext) field_Query_userSearch_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *string + if tmp, ok := rawArgs["birthdate"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("birthdate")) + arg0, err = ec.unmarshalODate2ᚖstring(ctx, tmp) + if err != nil { + return nil, err + } + } + args["birthdate"] = arg0 + var arg1 *string + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg1, err = ec.unmarshalOID2ᚖstring(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg1 + return args, nil +} + func (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -1032,6 +1071,45 @@ func (ec *executionContext) _Query_usersBornOnDates(ctx context.Context, field g return ec.marshalNUser2ᚕᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐUserᚄ(ctx, field.Selections, res) } +func (ec *executionContext) _Query_userSearch(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_userSearch_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().UserSearch(rctx, args["birthdate"].(*string), args["id"].(*string)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*User) + fc.Result = res + return ec.marshalOUser2ᚕᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐUser(ctx, field.Selections, res) +} + func (ec *executionContext) _Query_fail(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -2628,6 +2706,17 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } return res }) + case "userSearch": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_userSearch(ctx, field) + return res + }) case "fail": field := field out.Concurrently(i, func() (res graphql.Marshaler) { @@ -3516,6 +3605,46 @@ func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel as return graphql.MarshalString(*v) } +func (ec *executionContext) marshalOUser2ᚕᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐUser(ctx context.Context, sel ast.SelectionSet, v []*User) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalOUser2ᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐUser(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + func (ec *executionContext) marshalOUser2ᚖgithubᚗcomᚋKhanᚋgenqlientᚋinternalᚋintegrationᚋserverᚐUser(ctx context.Context, sel ast.SelectionSet, v *User) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/internal/integration/server/server.go b/internal/integration/server/server.go index 3883504c..d0412b09 100644 --- a/internal/integration/server/server.go +++ b/internal/integration/server/server.go @@ -107,6 +107,17 @@ func (r *queryResolver) UsersBornOnDates(ctx context.Context, dates []string) ([ return usersByBirthdates(dates), nil } +func (r *queryResolver) UserSearch(ctx context.Context, birthdate *string, id *string) ([]*User, error) { + switch { + case birthdate == nil && id != nil: + return []*User{userByID(*id)}, nil + case birthdate != nil && id == nil: + return usersByBirthdates([]string{*birthdate}), nil + default: + return nil, fmt.Errorf("need exactly one of birthdate or id") + } +} + func (r *queryResolver) Fail(ctx context.Context) (*bool, error) { f := true return &f, fmt.Errorf("oh no") diff --git a/internal/testutil/types.go b/internal/testutil/types.go index 9d5243cc..e160a121 100644 --- a/internal/testutil/types.go +++ b/internal/testutil/types.go @@ -36,10 +36,6 @@ func MarshalDate(t *time.Time) ([]byte, error) { func UnmarshalDate(b []byte, t *time.Time) error { // (modified from time.Time.UnmarshalJSON) - if string(b) == "null" { - return nil - } - var err error *t, err = time.Parse(`"`+dateFormat+`"`, string(b)) return err