MarshalJSON not called in some cases
The generated MarshalJSON() implementation currently has a pointer receiver:
func (msg *Foo) MarshalJSON() ([]byte, error) {
//...
}
Generally this is fine, as protobufs aren't value-copyable and are almost always used in a pointer context, but if it's not a value receiver, there are subtle places where the json.Marshaler function won't be called properly.
For example:
type EmbedFoo struct {
Foo
TimeToLive int `json:"ttl"`
}
func main() {
foo := Foo{}
_, _ = json.Marshal(foo) // FAIL, Does not call MarshalJSON
_, _ = json.Marshal(&foo) // OK
foo2 := EmbedFoo{}
_, _ = json.Marshal(foo2) // FAIL, Does not call MarshalJSON
_, _ = json.Marshal(&foo2) // FAIL, Does not call MarshalJSON
}
Changing the generated MarshalJSON to have value receiver fixes it (due to the pointer-following logic that json.Marshal() performs):
func (msg Foo) MarshalJSON() ([]byte, error) {
// ...
}
This would also mirror its common uses within Go itself (including the example in the docs):
func (a *Animal) UnmarshalJSON(b []byte) error {
// ...
}
func (a Animal) MarshalJSON() ([]byte, error) {
// ...
}
Note: This only applies to MarshalJSON. UnmarshalJSON should continue to have the pointer receiver.
@chkohner proto messages require a pointer receiver to implement proto.Message required by marshalling funcs: https://pkg.go.dev/google.golang.org/protobuf/encoding/protojson#Marshal