Skip to content

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

Closed
@greg-montoux

Description

@greg-montoux

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)

Activity

dsnet

dsnet commented on Sep 25, 2024

@dsnet
Collaborator

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

dsnet commented on Sep 25, 2024

@dsnet
Collaborator

Closing as inactionable.

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @dsnet@greg-montoux

        Issue actions

          omitempty behaviour on fields of type any differs from encoding/json · Issue #51 · go-json-experiment/json