Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

omitempty behaviour on fields of type any differs from encoding/json #51

Closed
greg-montoux opened this issue Sep 25, 2024 · 2 comments
Closed

Comments

@greg-montoux
Copy link

greg-montoux commented Sep 25, 2024

With jsonv2, when encoding a struct with a field of type of any and an omitempty tag, a empty string value will cause the field to be omitted. Whereas encoding/json only omits these fields when the value is nil.

This behaviour doesn't exactly match the docs:
https://pkg.go.dev/encoding/json#Marshal

The "omitempty" option specifies that the field should be omitted from the encoding if the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string.

Test to demonstrate difference in behaviour:

package jsonv2test

import (
	"bytes"
	"encoding/json"
	"testing"

	jsonv2 "github.com/go-json-experiment/json"
)

func TestOmitEmpty(t *testing.T) {

	type Foo struct {
		Bar any `json:",omitempty"`
	}

	foo := Foo{Bar: ""}

	bs, err := json.Marshal(foo)
	if err != nil {
		t.Fatal(err)
	}

	bs2, err := jsonv2.Marshal(foo)
	if err != nil {
		t.Fatal(err)
	}

	if !bytes.Equal(bs, bs2) {
		t.Fatalf("not equal:\n%s\n%s", bs, bs2)
	}
}

Output:

=== RUN   TestOmitEmpty
    jsonv2_test.go:30: not equal:
        {"Bar":""}
        {}
--- FAIL: TestOmitEmpty (0.00s)
@dsnet
Copy link
Collaborator

dsnet commented Sep 25, 2024

Hi, thanks for the report. You are correct that it does not perform identically.

The meaning of omitempty is altered in v2 to be:

the struct field should be omitted if the field value would have been encoded as a JSON null, empty string, empty object, or empty array.

The problem with omitempty in v1 is that the definition was too narrow (e.g., it couldn't omit struct types). The omitzero option is being added to expand this and will be backported into v1 "encoding/json". See golang/go#45669. Most usages of omitempty should probably be using omitzero in the future.

You can read golang/go#63397 (comment) for more information.

@dsnet
Copy link
Collaborator

dsnet commented Sep 25, 2024

Closing as inactionable.

Feel free to continue discussion at golang/go#63397 (comment).

@dsnet dsnet closed this as completed Sep 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants