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

feature: CBOR uses a different definition of "empty" than golang encoding/json for omitempty #445

Closed
dinhxuanvu opened this issue Dec 7, 2023 · 3 comments
Assignees
Labels
enhancement New feature or request

Comments

@dinhxuanvu
Copy link
Contributor

Is your feature request related to a problem? Please describe.
My team is working on using CBOR along side of JSON for encoding internal golang type and notice that if we convert a go struct with omitempty tag in some case, the results don't match the JSON due to the fact CBOR uses a different definition of empty compared to encoding/json library in go.

For example, consider this go struct:

type Foo struct {
 Bar struct{} `json:"bar,omitemptry"`
}

If we marshal this struct into JSON, the Bar field will be reserved but in CBOR, it will be omitted completely. The reason is in go library, 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 while in CBOR, an empty struct is also considered empty value. It would be helpful to have both of them using the same definition to ensure no data loss during the decoding process.

Describe the solution you'd like
We would like to add a decode option to enforce the parity between golang encoding/json library and CBOR. This option will not introduce any breaking changes given this option needs to be enabled by users.

Describe alternatives you've considered
We can change the behaviors in isEmptyStruct directly to match the ones in golang but this is a breaking change.

Additional context
We are happy to open the PR for this work.

@fxamacker
Copy link
Owner

@dinhxuanvu Thanks for opening this issue! It makes sense, please feel free to open a PR.

BTW, fxamacker/cbor currently handles omitempty more similar to Go's proposed encoding/json/v2.

Go's encoding/json and proposed encoding/json/v2 handle omitempty this way:

  • Current: encoding/json omits if field value is an empty Go value.
  • Future: encoding/json/v2 omits if field value would encode as empty JSON value.

Also, here is a more complex omitempty example you might find useful. If all fields of a nested struct are omitted, and the nested struct is tagged with omitempty, then the nested struct itself is omitted.

https://go.dev/play/p/0XUKz6bR6zN

	type T1 struct {
		Bo    bool           `cbor:"bo,omitempty"`
		UIo   uint           `cbor:"uio,omitempty"`
		Io    int            `cbor:"io,omitempty"`
		Fo    float64        `cbor:"fo,omitempty"`
		So    string         `cbor:"so,omitempty"`
		Slco  []string       `cbor:"slco,omitempty"`
		Mo    map[int]string `cbor:"mo,omitempty"`
		Po    *int           `cbor:"po,omitempty"`
		Intfo interface{}    `cbor:"intfo,omitempty"`
	}
	type T struct {
		Str  T1 `cbor:"str"`
		Stro T1 `cbor:"stro,omitempty"`
	}

	v := T{}

	b, _ := cbor.Marshal(v)
	fmt.Printf("CBOR in hex: 0x%xn\n", b) // CBOR in hex: 0xa163737472a0n

	edn, _ := cbor.Diagnose(b)
	fmt.Printf("CBOR in EDN: %s\n", edn) // CBOR in EDN: {"str": {}}

@dinhxuanvu
Copy link
Contributor Author

dinhxuanvu commented Dec 8, 2023

@fxamacker Thanks for the info. I wasn't aware of this encoding/json/v2 proposal. I appreciate the pointer.

I will open the PR for this issue and will put a note to indicate that this work is intended to enforce parity between the current v1 encoding/json and CBOR as I think it is still helpful for the time being and for those who want to stick with v1 for a bit longer. I will notice that v2 will match the current behavior of CBOR.

@dinhxuanvu
Copy link
Contributor Author

The feature has been completed.
/close

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants