IvanR
Nestru: serialize maps to nested structs
The Nestru library can convert a map of any shape into a model of nested structs according to given hints. And It can convert any nested struct into a map.
The library’s primary purpose is to serialize between JSON map and an application’s model that is a struct having other structs nested in it.
It comes from the idea to have no DSL and less custom code to parse JSONs as an alternative to full-fledged Ecto with schemaless changesets.
Works good in Jason <-> Nestru pair.
There are several possible data validation options:
- with ex_json_schema applied to the map before passing to Nestru
- within Nestru
gather_fields_map/3andfrom_map_hint/3callbacks - with Ecto schemaless changesets applied to the struct
- with Domo applied to the struct to validate the struct conformance to its
@type t()and associated preconditions
See typical usage in Readme.md via:
Shortly it looks like:
defmodule Order do
@derive [
Nestru.Encoder,
{Nestru.Decoder, %{items: [LineItem], total: Total}}
]
# Gave a hint to Nestru on how to process the items and total fields
# others go to a struct as is.
defstruct [:id, :items, :total]
end
defmodule LineItem do
@derive [Nestru.Encoder, Nestru.Decoder]
defstruct [:amount]
end
defmodule Total do
@derive [Nestru.Encoder, Nestru.Decoder]
defstruct [:sum]
end
map = %{
"id" => "A548",
"items" => [%{"amount" => 150}, %{"amount" => 350}],
"total" => %{"sum" => 500}
}
{:ok, model} = Nestru.decode_from_map(map, Order)
returns:
{:ok,
%OrderA{
id: "A548",
items: [%LineItemA{amount: 150}, %LineItemA{amount: 350}],
total: %Total{sum: 500}
}}
And going back to the map is as simple as that:
map = Nestru.encode_to_map(model)
returns:
%{
id: "A548",
items: [%{amount: 150}, %{amount: 350}],
total: %{sum: 500}
}
More information here:
Most Liked
IvanR
0.2.0 - August 16, 2022
- Fix to ensure the module is loaded before checking if it’s a struct
- Add
decodeandencodeverbs to function names - Support
[Module]hint in the map returned fromfrom_map_hintto decode the list of structs - Support
%{one_key: :other_key}mapping configuration for thePreDecoderprotocol in@deriveattribute.
Now, for most common decoding cases, it’s possible to configure decoding fully in a declarative way by providing param maps when deriving protocols like that:
defmodule Order do
@derive [
{Nestru.PreDecoder, %{"attrs" => :total}},
{Nestru.Decoder, %{total: Total}}
]
defstruct [:id, :total]
end
defmodule Total do
@derive Nestru.Decoder
defstruct [:sum]
end
so the decoding works like that:
Nestru.decode_from_map(%{"attrs" => %{"sum" => 568}, "id" => "A874"}, Order)
{:ok, %Order{id: "A874", total: %Total{sum: 568}}}
IvanR
IvanR
0.1.1 - November 13, 2021
-
Add
has_key?/2andget/3map functions that lookup keys in maps both in a binary or an atom form. -
Add the link to open Readme.md in LiveBook

Last Post!
IvanR
0.3.1 - November 22, 2022
- Add
:onlyand:exceptoptions for deriving ofNestru.Encoderprotocol (hommage forJason.Encoderapproach
) - Add explicit
:translateoption for deriving ofNestru.PreDecoderprotocol - Add explicit
:hintoption for deriving ofNestru.Decoderprotocol
See the documentation for examples.
Popular in Announcing
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex









