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
- Is my objective possible using the Jason library, or is this a limitation?
- Am I miss understanding the documentation and doing something incorrect?