go-json icon indicating copy to clipboard operation
go-json copied to clipboard

`omitempty` tag is ignored when field's type has pointer receiver in `MarshalJSON` implementation

Open GCrispino opened this issue 1 year ago • 0 comments

Description

Consider any struct type A with a field F tagged as omitempty, where F has type B. If B has a custom MarshalJSON implementation with a pointer receiver, for values of A where F has an empty value the empty value of F is not omitted as it should.

This seems similar to https://github.com/goccy/go-json/issues/458, but tried its fix for this and it did not work.

Example

Consider the type stringAlias with a custom MarshalJSON implementation with a pointer receiver:

type stringAlias string

func (d *stringAlias) MarshalJSON() ([]byte, error) {
	return []byte(fmt.Sprintf("\"%s\"", *d)), nil
}

Now consider type withOmit, which has a field A tagged as omitempty, having type stringAlias:

type withOmit struct {
	A stringAlias `json:"a,omitempty"`
}

For values of withOmit with empty values of A, go-json fails to omit values of this field:

func main() {
	var correct, wrong withOmit

	bytesCorrect, err := stdJson.Marshal(&correct) // "stdJson" is "encoding/json"
	if err != nil {
		panic(err)
	}

	bytesWrong, err := json.Marshal(&wrong)
	if err != nil {
		panic(err)
	}

	fmt.Printf("correct: %s\n", bytesCorrect) // correct: {}
	fmt.Printf("wrong: %s\n", bytesWrong)     // wrong: {"a":""}
}

Full code example available at https://go.dev/play/p/4njSDtWS8k5 (couldn't make it run though, it times out when downloading dependencies).

GCrispino avatar Dec 18 '23 00:12 GCrispino