How to have custom enconding for struct using Jason?

Background

I am trying to encode a structure into json format using the Jason library. However, this is not working as expected.

Code

Let’s assume I have this struct:

defmodule Test do defstruct [:foo, :bar, :baz] end 

And that when using Jason.enconde(%Test{foo: 1, bar: 2, baz:3 }) I want this json to be created:

%{"foo" => 1, "banana" => 5} 

Error

It is my understanding that to achieve this I need to implement the Jason.Enconder protocol in my struct:
https://hexdocs.pm/jason/Jason.Encoder.html

defmodule Test do defstruct [:foo, :bar, :baz] defimpl Jason.Encoder do @impl Jason.Encoder def encode(value, opts) do Jason.Encode.map(%{foo: Map.get(value, :foo), banana: Map.get(value, :bar, 0) + Map.get(value, :baz, 0)}, opts) end end end 

However, this will not work:

Jason.encode(%Test{foo: 1, bar: 2, baz: 3}) {:error, %Protocol.UndefinedError{ description: "Jason.Encoder protocol must always be explicitly implemented.\n\nIf you own the struct, you can derive the implementation specifying which fields should be encoded to JSON:\n\n @derive {Jason.Encoder, only: [....]}\n defstruct ...\n\nIt is also possible to encode all fields, although this should be used carefully to avoid accidentally leaking private information when new fields are added:\n\n @derive Jason.Encoder\n defstruct ...\n\nFinally, if you don't own the struct you want to encode to JSON, you may use Protocol.derive/3 placed outside of any module:\n\n Protocol.derive(Jason.Encoder, NameOfTheStruct, only: [...])\n Protocol.derive(Jason.Encoder, NameOfTheStruct)\n", protocol: Jason.Encoder, value: %Test{bar: 2, baz: 3, foo: 1} }} 

From what I understand, it looks like I can only select/exclude keys to serialize, I cannot transform/add new keys.
Since I own the structure in question, using Protocol.derive is not necessary.

However I fail to understand how I can leverage the Jason.Encoder protocol to achieve what I want.

Questions

  1. Is my objective possible using the Jason library, or is this a limitation?
  2. Am I miss understanding the documentation and doing something incorrect?
2 Likes