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

dimitarvp
I needed exactly this two weeks ago, thanks for making it. 
dredison
This is 100% exactly the library I needed. Thank you! (and again the extra time you spent on the documentation).








