go icon indicating copy to clipboard operation
go copied to clipboard

omitempty does not work with MarshalJSON and a pointer receiver

Open dsazonov-tv opened this issue 3 years ago • 2 comments

If there is an implementation of MarshalJSON for a type and the receiver is a pointer, then omitempty tag will be ignored by jsoniterator.Marshal even if the field of that type is not a pointer. The standard library works as expected. For example:

type MyStr string
type MyBrokenStr string

func (str *MyBrokenStr) MarshalJSON() ([]byte, error) {
	if str == nil {
		return []byte(`""`), nil
	}
	return []byte(fmt.Sprintf(`"%s"`, *str)), nil
}

type Foo struct {
	Bar MyStr       `json:"bar,omitempty"`
	Baz MyBrokenStr `json:"baz,omitempty"`
}

func TestOmitempty(t *testing.T) {
	jsiter := jsoniterator.ConfigCompatibleWithStandardLibrary
	foo := &Foo{} // all fields are empty, so they must be ignored
	expected, _ := json.Marshal(foo)
	actual, _ := jsiter.Marshal(foo)
	if string(expected) != string(actual) {
		t.Fatalf(`expected: "%s", actual "%s"`, expected, actual)
	}
}

will produce expected: "{}", actual "{"baz":""}".

dsazonov-tv avatar Aug 03 '22 12:08 dsazonov-tv

this will also happen in standard encoding/json library

bearbearkeeper avatar Oct 20 '23 05:10 bearbearkeeper

But in my example you can find the following lines:

expected, _ := json.Marshal(foo) // standard library
actual, _ := jsiter.Marshal(foo) // jsoniter

And those lines produce different output.

dsazonov-tv avatar Nov 22 '23 16:11 dsazonov-tv