connectrpc / connect-go

The Go implementation of Connect: Protobuf RPC that works.
https://connectrpc.com
Apache License 2.0
2.76k stars 91 forks source link

Custom marshal options for protojson (e.g. emitting zero-value fields in JSON) #676

Closed mitioshi closed 5 months ago

mitioshi commented 5 months ago

This PR adds a new handler option option to customize the Marshaling behavior.

Motivation

Right now, there is no way to customize the JSON output generated by json handlers. This leads to zero values being always omitted. For some, this behavior is undesirable. protobuf users usually tweak protojson output by disabling omitting of zero-value fields via EmitDefaults from https://pkg.go.dev/google.golang.org/protobuf/encoding/protojson#MarshalOptions. With this flag enabled, zero-value fields are properly outputted to the resulting json. I'd be good to bring this functionality to connect as well

Usage

connect-go users may now use it like this:

path, handler := usersv1connect.NewUsersServiceHandler(
    users,
    connect.WithCustomProtoJSON(connect.ProtoJSONOptions{EmitDefaultValues: true}),
)

Notes on the implementation

I've decided to add a new option instead of adding a new parameter to connect.WithProtoJSON to not break any clients.

What do you guys think?

CLAassistant commented 5 months ago

CLA assistant check
All committers have signed the CLA.

jhump commented 5 months ago

@mitioshi, we've tried to avoid having too many of the protobuf-go runtime packages show up in the exported API. While we might consider adding the ability to configure serialization parameters in the future, for now I'd suggest using https://github.com/akshayjshah/connectproto. That repo has a connectproto.WithJSON function that lets you customize the behavior, and it returns options you can supply to connect clients and handlers.

mitioshi commented 5 months ago

@jhump I see. It might be a good idea to describe that in readme and tell people to use https://github.com/akshayjshah/connectproto for now. Otherwise people like me wouldn't stop trying to reimplement this option =)