View Source Syrup.Encoder protocol (Syrup v0.4.0)
Protocol controlling how a value is encoded to Syrup.
Deriving
The protocol allows leveraging Elixir's @derive
feature
to simplify protocol implementtaion in trivial cases. Accepted
options are:
:only
- encodes only values of specific keys.:except
- encodes all struct fields except specific keys.:as
- the type of the encoding to use. Can be:map
or:record
.:label
- record name to use instead of the struct name if serializing as a record.
By default all keys except the :__struct__
key are encoded.
Example
Let's assume a presence of the following struct:
defmodule Test do
defstruct [:foo, :bar, :baz]
end
If we were to call @derive Syrup.Encoder
just before defstruct
,
an implementation similar to the following implementation would be generated:
defimpl Syrup.Encoder, for: Test do
def encode(value, opts) do
Syrup.Encode.record(Map.take(value, [:foo, :bar, :baz]), Keyword.put_new(opts, :as, "Test"))
end
end
If we called @derive {Syrup.Encoder, only: [:foo]}
, an implementation
similar to the following implementation would be generated:
defimpl Syrup.Encoder, for: Test do
def encode(value, opts) do
Syrup.Encode.record(Map.take(value, [:foo]), Keyword.put_new(opts, :as, "Test"))
end
end
If we called @derive {Syrup.Encoder, except: [:foo]}
, an implementation
similar to the following implementation would be generated:
defimpl Syrup.Encoder, for: Test do
def encode(value, opts) do
Syrup.Encode.record(Map.take(value, [:bar, :baz]), Keyword.put_new(opts, :as, "Test"))
end
end
If we called @derive {Syrup.Encoder, as: "test"}
, an implementation
similar to the following implementation would be generated:
defimpl Syrup.Encoder, for: Test do
def encode(value, opts) do
Syrup.Encode.record(Map.take(value, [:foo, :bar, :baz]), Keyword.put_new(opts, :as, "test"))
end
end
The actually generated implementations are more efficient computing some data
during compilation similar to the macros from the Syrup.Helpers
module.
Overriding the generated implementation
If you wish to override the generated implementation, you can do so by
defining either the to_syrup_map/1
or to_syrup_record/1
functions in
the module for which the protocol is derived. Which one to override depends
on the Syrup representation you have selected in the derivation (the :as
option above).
This is most useful if the
Syrup representation of the struct has static metadata that doesn't need
to be stored in the struct, or if the structure of the Syrup representation
is not a simple record or map.
Explicit implementation
If you wish to implement the protocol fully yourself, it is advised to
use functions from the Syrup.Encode
module to do the actual encoding.
They are highly optimized and verified to always produce valid Syrup.
Summary
Functions
Encodes value
to Syrup.
Types
@type opts() :: Syrup.Encode.opts()
@type t() :: term()
Functions
Encodes value
to Syrup.
The argument opts
is opaque - it can be passed to various functions in
Syrup.Encode
(or to the protocol function itself) for encoding values to Syrup.