In general the protocol implementation is a bad idea for encoding domain entities like ecto structs - it’s very likely you’d like to differ how you encode them in different situations and protocols are global.
The way to go is to use phoenix views to translate from structs to simple data that can be encoded - take a look at the default code phoenix generates when you use phx.gen.json
.