IvanR

IvanR

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/3 and from_map_hint/3 callbacks
  • 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:

Run in Livebook

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

IvanR OP

0.2.0 - August 16, 2022

  • Fix to ensure the module is loaded before checking if it’s a struct
  • Add decode and encode verbs to function names
  • Support [Module] hint in the map returned from from_map_hint to decode the list of structs
  • Support %{one_key: :other_key} mapping configuration for the PreDecoder protocol in @derive attribute.

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 OP

0.2.1 - August 20, 2022

  • Fix decode_from_map(!)/2/3 to return the error for not a map value
IvanR

IvanR OP

0.1.1 - November 13, 2021

  • Add has_key?/2 and get/3 map functions that lookup keys in maps both in a binary or an atom form.

  • Add the link to open Readme.md in LiveBook :slightly_smiling_face:

Last Post!

IvanR

IvanR OP

0.3.1 - November 22, 2022

  • Add :only and :except options for deriving of Nestru.Encoder protocol (hommage for Jason.Encoder approach :slightly_smiling_face:)
  • Add explicit :translate option for deriving of Nestru.PreDecoder protocol
  • Add explicit :hint option for deriving of Nestru.Decoder protocol

See the documentation for examples.

Where Next? Top

Trending in Announcing Top

woylie
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries. offset-based pagination with...
New
MRdotB
I needed to reuse React components from my Chrome extension in my Phoenix/LiveView backend. I noticed that for Svelte/Vue, there are live...
New
woylie
I released Doggo, a collection of unstyled Phoenix components. https://github.com/woylie/doggo Features Unstyled Phoenix components....
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
anuaralfetahe
Hello Published a new library - ProcessHub! ProcessHub is a library designed to manage process distribution within the Elixir cluster. ...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
sergio
It’s not that it’s vocabulary is too advanced. It’s something worse. I get lost trying to follow even a paragraph written by Claude. It’...
New
AstonJ
This showed up on my feed.. anyone heard of it? Just hype? Ox Alpha is a reasoning model designed for coding, sustained ag...
New
bartblast
Hey folks, I just published a post about Hologram’s funding and where the project goes next - the short version: Curiosum as Main Spons...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews