fix: premarshal structs get generated with omitempty tag (#267)
This PR addresses a bug described in #263 Basically, whenever a struct involves a custom genqlient binding, a secondary "premarshal" struct gets generated. The bug was that this "premarshal" struct was not propagating the `omitempty` JSON tags, which was resulting in unexpected behavior. The fix involved a few changed lines in the Go template, and a few changes in the unit tests. I have: - [x] Written a clear PR title and description (above) - [x] Signed the [Khan Academy CLA](https://www.khanacademy.org/r/cla) - [x] Added tests covering my changes, if applicable - [x] Included a link to the issue fixed, if applicable - [x] Included documentation, for new features (n/a) - [x] Added an entry to the changelog
This commit is contained in:
@@ -34,6 +34,7 @@ When releasing a new version:
|
||||
- Fixed non-deterministic generated code when querying graphql interfaces.
|
||||
- Fixed generated code when last component of package name is not a valid identifier (e.g. `"path/to/my-package"`).
|
||||
- Fixed incorrect documentation of `for` directive.
|
||||
- Fixed bug where `omitempty` JSON tags were not being correctly applied to `__premarshal` structs.
|
||||
|
||||
## v0.5.0
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
type __premarshal{{.GoName}} struct{
|
||||
{{range .FlattenedFields -}}
|
||||
{{if .NeedsMarshaling -}}
|
||||
{{.GoName}} {{repeat .GoType.SliceDepth "[]"}}{{ref "encoding/json.RawMessage"}} `json:"{{.JSONName}}"`
|
||||
{{.GoName}} {{repeat .GoType.SliceDepth "[]"}}{{ref "encoding/json.RawMessage"}} `json:"{{.JSONName}}{{if .Omitempty -}},omitempty{{end}}"`
|
||||
{{else}}
|
||||
{{.GoName}} {{.GoType.Reference}} `json:"{{.JSONName}}"`
|
||||
{{.GoName}} {{.GoType.Reference}} `json:"{{.JSONName}}{{if .Omitempty -}},omitempty{{end}}"`
|
||||
{{end}}
|
||||
{{end}}
|
||||
}
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
# @genqlient(pointer: true)
|
||||
query GetPokemon($where: getPokemonBoolExp!) {
|
||||
getPokemon(where: $where) {
|
||||
species
|
||||
level
|
||||
}
|
||||
}
|
||||
+20
@@ -180,8 +180,28 @@ type Query {
|
||||
listOfListsOfListsOfContent: [[[Content!]!]!]!
|
||||
recur(input: RecursiveInput!): Recursive
|
||||
acceptsListOfListOfListsOfDates(datesss: [[[Date!]!]!]!): Boolean
|
||||
getPokemon(where: getPokemonBoolExp): [Pokemon!]!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createUser(name: String!, email: String): User
|
||||
}
|
||||
|
||||
input getPokemonBoolExp {
|
||||
_and: [getPokemonBoolExp!]
|
||||
_not: getPokemonBoolExp
|
||||
_or: [getPokemonBoolExp!]
|
||||
level: IntComparisonExp
|
||||
}
|
||||
|
||||
input IntComparisonExp {
|
||||
_eq: Int
|
||||
_gt: Int
|
||||
_gte: Int
|
||||
_in: [Int!]
|
||||
_isNull: Boolean
|
||||
_lt: Int
|
||||
_lte: Int
|
||||
_neq: Int
|
||||
_nin: [Int!]
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
// Code generated by github.com/Khan/genqlient, DO NOT EDIT.
|
||||
|
||||
package test
|
||||
|
||||
import (
|
||||
"github.com/Khan/genqlient/graphql"
|
||||
"github.com/Khan/genqlient/internal/testutil"
|
||||
)
|
||||
|
||||
type GetPokemonBoolExp struct {
|
||||
And []*GetPokemonBoolExp `json:"_and"`
|
||||
Not *GetPokemonBoolExp `json:"_not"`
|
||||
Or []*GetPokemonBoolExp `json:"_or"`
|
||||
Level *IntComparisonExp `json:"level"`
|
||||
}
|
||||
|
||||
// GetAnd returns GetPokemonBoolExp.And, and is useful for accessing the field via an interface.
|
||||
func (v *GetPokemonBoolExp) GetAnd() []*GetPokemonBoolExp { return v.And }
|
||||
|
||||
// GetNot returns GetPokemonBoolExp.Not, and is useful for accessing the field via an interface.
|
||||
func (v *GetPokemonBoolExp) GetNot() *GetPokemonBoolExp { return v.Not }
|
||||
|
||||
// GetOr returns GetPokemonBoolExp.Or, and is useful for accessing the field via an interface.
|
||||
func (v *GetPokemonBoolExp) GetOr() []*GetPokemonBoolExp { return v.Or }
|
||||
|
||||
// GetLevel returns GetPokemonBoolExp.Level, and is useful for accessing the field via an interface.
|
||||
func (v *GetPokemonBoolExp) GetLevel() *IntComparisonExp { return v.Level }
|
||||
|
||||
// GetPokemonResponse is returned by GetPokemon on success.
|
||||
type GetPokemonResponse struct {
|
||||
GetPokemon []*testutil.Pokemon `json:"getPokemon"`
|
||||
}
|
||||
|
||||
// GetGetPokemon returns GetPokemonResponse.GetPokemon, and is useful for accessing the field via an interface.
|
||||
func (v *GetPokemonResponse) GetGetPokemon() []*testutil.Pokemon { return v.GetPokemon }
|
||||
|
||||
type IntComparisonExp struct {
|
||||
Eq *int `json:"_eq"`
|
||||
Gt *int `json:"_gt"`
|
||||
Gte *int `json:"_gte"`
|
||||
In []*int `json:"_in"`
|
||||
IsNull *bool `json:"_isNull"`
|
||||
Lt *int `json:"_lt"`
|
||||
Lte *int `json:"_lte"`
|
||||
Neq *int `json:"_neq"`
|
||||
Nin []*int `json:"_nin"`
|
||||
}
|
||||
|
||||
// GetEq returns IntComparisonExp.Eq, and is useful for accessing the field via an interface.
|
||||
func (v *IntComparisonExp) GetEq() *int { return v.Eq }
|
||||
|
||||
// GetGt returns IntComparisonExp.Gt, and is useful for accessing the field via an interface.
|
||||
func (v *IntComparisonExp) GetGt() *int { return v.Gt }
|
||||
|
||||
// GetGte returns IntComparisonExp.Gte, and is useful for accessing the field via an interface.
|
||||
func (v *IntComparisonExp) GetGte() *int { return v.Gte }
|
||||
|
||||
// GetIn returns IntComparisonExp.In, and is useful for accessing the field via an interface.
|
||||
func (v *IntComparisonExp) GetIn() []*int { return v.In }
|
||||
|
||||
// GetIsNull returns IntComparisonExp.IsNull, and is useful for accessing the field via an interface.
|
||||
func (v *IntComparisonExp) GetIsNull() *bool { return v.IsNull }
|
||||
|
||||
// GetLt returns IntComparisonExp.Lt, and is useful for accessing the field via an interface.
|
||||
func (v *IntComparisonExp) GetLt() *int { return v.Lt }
|
||||
|
||||
// GetLte returns IntComparisonExp.Lte, and is useful for accessing the field via an interface.
|
||||
func (v *IntComparisonExp) GetLte() *int { return v.Lte }
|
||||
|
||||
// GetNeq returns IntComparisonExp.Neq, and is useful for accessing the field via an interface.
|
||||
func (v *IntComparisonExp) GetNeq() *int { return v.Neq }
|
||||
|
||||
// GetNin returns IntComparisonExp.Nin, and is useful for accessing the field via an interface.
|
||||
func (v *IntComparisonExp) GetNin() []*int { return v.Nin }
|
||||
|
||||
// __GetPokemonInput is used internally by genqlient
|
||||
type __GetPokemonInput struct {
|
||||
Where *GetPokemonBoolExp `json:"where"`
|
||||
}
|
||||
|
||||
// GetWhere returns __GetPokemonInput.Where, and is useful for accessing the field via an interface.
|
||||
func (v *__GetPokemonInput) GetWhere() *GetPokemonBoolExp { return v.Where }
|
||||
|
||||
// The query or mutation executed by GetPokemon.
|
||||
const GetPokemon_Operation = `
|
||||
query GetPokemon ($where: getPokemonBoolExp!) {
|
||||
getPokemon(where: $where) {
|
||||
species
|
||||
level
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
func GetPokemon(
|
||||
client graphql.Client,
|
||||
where *GetPokemonBoolExp,
|
||||
) (*GetPokemonResponse, error) {
|
||||
req := &graphql.Request{
|
||||
OpName: "GetPokemon",
|
||||
Query: GetPokemon_Operation,
|
||||
Variables: &__GetPokemonInput{
|
||||
Where: where,
|
||||
},
|
||||
}
|
||||
var err error
|
||||
|
||||
var data GetPokemonResponse
|
||||
resp := &graphql.Response{Data: &data}
|
||||
|
||||
err = client.MakeRequest(
|
||||
nil,
|
||||
req,
|
||||
resp,
|
||||
)
|
||||
|
||||
return &data, err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"operations": [
|
||||
{
|
||||
"operationName": "GetPokemon",
|
||||
"query": "\nquery GetPokemon ($where: getPokemonBoolExp!) {\n\tgetPokemon(where: $where) {\n\t\tspecies\n\t\tlevel\n\t}\n}\n",
|
||||
"sourceLocation": "testdata/queries/Hasura.graphql"
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+14
-14
@@ -83,19 +83,19 @@ func (v *MyInput) UnmarshalJSON(b []byte) error {
|
||||
}
|
||||
|
||||
type __premarshalMyInput struct {
|
||||
Email *string `json:"email"`
|
||||
Email *string `json:"email,omitempty"`
|
||||
|
||||
Name *string `json:"name"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
|
||||
Id *testutil.ID `json:"id"`
|
||||
Id *testutil.ID `json:"id,omitempty"`
|
||||
|
||||
Role *Role `json:"role"`
|
||||
Role *Role `json:"role,omitempty"`
|
||||
|
||||
Names []*string `json:"names"`
|
||||
Names []*string `json:"names,omitempty"`
|
||||
|
||||
HasPokemon *testutil.Pokemon `json:"hasPokemon"`
|
||||
HasPokemon *testutil.Pokemon `json:"hasPokemon,omitempty"`
|
||||
|
||||
Birthdate json.RawMessage `json:"birthdate"`
|
||||
Birthdate json.RawMessage `json:"birthdate,omitempty"`
|
||||
}
|
||||
|
||||
func (v *MyInput) MarshalJSON() ([]byte, error) {
|
||||
@@ -264,19 +264,19 @@ func (v *UserQueryInput) UnmarshalJSON(b []byte) error {
|
||||
}
|
||||
|
||||
type __premarshalUserQueryInput struct {
|
||||
Email *string `json:"email"`
|
||||
Email *string `json:"email,omitempty"`
|
||||
|
||||
Name *string `json:"name"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
|
||||
Id *testutil.ID `json:"id"`
|
||||
Id *testutil.ID `json:"id,omitempty"`
|
||||
|
||||
Role *Role `json:"role"`
|
||||
Role *Role `json:"role,omitempty"`
|
||||
|
||||
Names []*string `json:"names"`
|
||||
Names []*string `json:"names,omitempty"`
|
||||
|
||||
HasPokemon *testutil.Pokemon `json:"hasPokemon"`
|
||||
HasPokemon *testutil.Pokemon `json:"hasPokemon,omitempty"`
|
||||
|
||||
Birthdate json.RawMessage `json:"birthdate"`
|
||||
Birthdate json.RawMessage `json:"birthdate,omitempty"`
|
||||
}
|
||||
|
||||
func (v *UserQueryInput) MarshalJSON() ([]byte, error) {
|
||||
|
||||
+6
-6
@@ -148,19 +148,19 @@ func (v *UserQueryInput) UnmarshalJSON(b []byte) error {
|
||||
}
|
||||
|
||||
type __premarshalUserQueryInput struct {
|
||||
Email string `json:"email"`
|
||||
Email string `json:"email,omitempty"`
|
||||
|
||||
Name string `json:"name"`
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
Id testutil.ID `json:"id"`
|
||||
|
||||
Role Role `json:"role"`
|
||||
Role Role `json:"role,omitempty"`
|
||||
|
||||
Names []string `json:"names"`
|
||||
Names []string `json:"names,omitempty"`
|
||||
|
||||
HasPokemon testutil.Pokemon `json:"hasPokemon"`
|
||||
HasPokemon testutil.Pokemon `json:"hasPokemon,omitempty"`
|
||||
|
||||
Birthdate json.RawMessage `json:"birthdate"`
|
||||
Birthdate json.RawMessage `json:"birthdate,omitempty"`
|
||||
}
|
||||
|
||||
func (v *UserQueryInput) MarshalJSON() ([]byte, error) {
|
||||
|
||||
Reference in New Issue
Block a user