{{/* See unmarshal.go.tmpl for more on how this works; this is mostly just parallel (and simplified -- we don't need to handle embedding). */}} func (v *{{.GoName}}) MarshalJSON() ([]byte, error) { {{/* We do the two passes in the opposite order of unmarshal: first, we marshal the special fields, then we assign those to the wrapper struct and finish marshaling the whole object. But first we set up the object for the second part, so we can assign to it as we go. */}} var fullObject struct{ *{{.GoName}} {{range .Fields -}} {{if .NeedsMarshaler -}} {{.GoName}} {{repeat .GoType.SliceDepth "[]"}}{{ref "encoding/json.RawMessage"}} `json:"{{.JSONName}}"` {{end -}} {{end -}} {{ref "github.com/Khan/genqlient/graphql.NoMarshalJSON"}} } fullObject.{{.GoName}} = v {{range $field := .Fields -}} {{if $field.NeedsMarshaler -}} { {{/* Here dst is the json.RawMessage, and src is the Go type */}} dst := &fullObject.{{$field.GoName}} src := v.{{$field.GoName}} {{range $i := intRange $field.GoType.SliceDepth -}} *dst = make( {{repeat (sub $field.GoType.SliceDepth $i) "[]"}}{{ref "encoding/json.RawMessage"}}, len(src)) for i, src := range src { dst := &(*dst)[i] {{end -}} var err error *dst, err = {{$field.Marshaler $.Generator}}( {{/* src is a pointer to 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. */ -}} {{if not $field.GoType.IsPointer}}&{{end}}src) if err != nil { return nil, fmt.Errorf( "Unable to marshal {{$.GoName}}.{{$field.GoName}}: %w", err) } {{range $i := intRange $field.GoType.SliceDepth -}} } {{end -}} } {{end -}} {{end}} return {{ref "encoding/json.Marshal"}}(&fullObject) }