golang / protobuf

Go support for Google's protocol buffers
BSD 3-Clause "New" or "Revised" License
9.66k stars 1.58k forks source link

How to emit defaults? #1515

Closed ivanjaros closed 1 year ago

ivanjaros commented 1 year ago

Since one should move away from this library to google, I have encountered a nasty bug where the marshaler will ignore empty slice(possibly maps as well) and so If I have [] in in json, I will end up with nil, which is WRONG. Empty and not-present are two VERY different states and removing omitempty from json tags will make things way way way worse. I have figured out the problem is that this library's marshaler has the "emit defaults" option that provides the behavior any sane person would expect to see and which I always used. And since these proto messages are not compatible with google's proto messages, I cannot use both libraries for "legacy" reasons. So my question is how to get this behavior back? Is there some 3rd party library that could fix this? It's json after all and the PB context is irrelevant.

ivanjaros commented 1 year ago

nevermind, the omitempty is the bast solution here.

ivanjaros commented 1 year ago

actually that does not solve anything. when someone sends me empty list, i need to know i got empty list and not nil(null/no value). I know there are the protobuf wrappers but those work only for concrete types. a list or a map will always be a pointer because it already is an object.

ivanjaros commented 1 year ago

actually using built-in json worked because it will handle nil, [] and {} properly. ..but it does not handle int64 :( .. this is hell

puellanivis commented 1 year ago

The JSON mapping of protobuf is provided as a way of encoding protobuf semantics in JSON, not as a general-purpose JSON encoding system. The proto3 JSON mapping specifically calls out that null is accepted as the empty list. And the default value for a repeated field is defined as an empty list.

I understand that there are time when one might want to distinguish a nil slice from a zero-length non-nil slice, and there are semantics available in JSON to encode this distinction. But protobuf has a different set of semantics, and those semantics need to be carried over into the JSON encoding for maximum protobuf compatibility.

Unfortunately, if you’re chafing against the protobuf semantics themselves, then protobuf maybe isn’t the right tool for what you want to get done.