View Source Msgpax.Packer protocol (Msgpax v2.4.0)

The Msgpax.Packer protocol is responsible for serializing any Elixir data structure according to the MessagePack specification.

Some notable properties of the implementation of this protocol for the built-in Elixir data structures:

  • atoms are encoded as strings (i.e., they're converted to strings first and then encoded as strings)
  • bitstrings can only be encoded as long as they're binaries (and not actual bitstrings - i.e., the number of bits must be a multiple of 8)
  • binaries (or Msgpax.Bin structs) containing 2^32 or more bytes cannot be encoded
  • maps with more than (2^32) - 1 elements cannot be encoded
  • lists with more than (2^32) - 1 elements cannot be encoded
  • integers larger than (2^64) - 1 or smaller than -2^63 cannot be encoded

serializing-a-subset-of-fields-for-structs

Serializing a subset of fields for structs

The Msgpax.Packer protocol supports serialization of only a subset of the fields of a struct when derived. For example:

defmodule User do
  @derive [{Msgpax.Packer, fields: [:name]}]
  defstruct [:name, :sensitive_data]
end

In the example, packing User will only serialize the :name field and leave out the :sensitive_data field. By default, the :__struct__ field is taken out of the struct before packing it. If you want this field to be present in the packed map, you have to set the :include_struct_field option to true.

unpacking-back-to-elixir-structs

Unpacking back to Elixir structs

When packing a struct, that struct will be packed as the underlying map and will be unpacked with string keys instead of atom keys. This makes it hard to reconstruct the map as tools like Kernel.struct/2 can't be used (given keys are strings). Also, unless specifically stated with the :include_struct_field option, the :__struct__ field is lost when packing a struct, so information about which struct it was is lost.

%User{name: "Juri"} |> Msgpax.pack!() |> Msgpax.unpack!()
#=> %{"name" => "Juri"}

These things can be overcome by using something like Maptu, which helps to reconstruct structs:

map = %User{name: "Juri"} |> Msgpax.pack!() |> Msgpax.unpack!()
Maptu.struct!(User, map)
#=> %User{name: "Juri"}

map =
  %{"__struct__" => "Elixir.User", "name" => "Juri"}
  |> Msgpax.pack!()
  |> Msgpax.unpack!()

Maptu.struct!(map)
#=> %User{name: "Juri"}

Link to this section Summary

Functions

This function serializes term.

Returns serialized infinity in 64-bit format.

Returns serialized NaN in 64-bit format.

Link to this section Types

Link to this section Functions

This function serializes term.

It returns an iodata result.

Returns serialized infinity in 64-bit format.

Returns serialized NaN in 64-bit format.