wingyplus

wingyplus

I just did a dirty hack after seeing Zoi on x.com a few hours ago.

Quick Introduction

The zoi_defstruct is a library to help you generate a struct from the Zoi object schema (over Zoi.object). Let’s see a small example below:

defmodule K8S.Deployment do
  use ZoiDefstruct

  @schema Zoi.object(%{
            apiVersion: Zoi.string(),
            metadata:
              Zoi.object(%{
                name: Zoi.string()
              }),
            spec:
              Zoi.object(%{
                replicas: Zoi.integer() |> Zoi.optional()
              })
          })

  defstructure(@schema)
end

When you call a defstructure The macro generates a struct with enforced keys and typespec for you automatically. So in the IEx, you can see:

A struct:

iex(4)> K8S.Deployment.__struct__()
%K8S.Deployment{spec: nil, metadata: nil, apiVersion: nil}

A typespec declaration:

iex(1)> t K8S.Deployment
@type t() :: %{
        spec: %{optional(:replicas) => integer()},
        metadata: %{name: binary()},
        apiVersion: binary()
      } 

ArgumentError if it has no required keys:

iex(5)> %K8S.Deployment{}
** (ArgumentError) the following keys must also be given when building struct K8S.Depl
oyment: [:spec, :metadata, :apiVersion]
    (examples 0.1.0) expanding struct: K8S.Deployment.__struct__/1
    iex:5: (file)

Since this is a quick hack, it has numerous edge cases that need to be addressed. Please feel free to provide feedback or suggestions. Opening an issue or pull request is very welcome.

I need to give special thanks to Zoi for making this awesome library!

https://github.com/wingyplus/zoi_defstruct

Showing Posts 1 to 9

byu

byu

Great. will check it out.

How does it differ from zoi/lib/zoi/struct.ex at main · phcurado/zoi · GitHub ?

phcurado

phcurado

awesome @wingyplus

You can leverage some of the helpers on the Zoi Struct module as @byu mentioned. I personally decided to not add any macros into the library (unless strictly necessary like infering type specs) but I added these helpers for anyone who wishes to extend it.
Thanks for using Zoi, awesome to see this

wingyplus

wingyplus OP

Thanks for the comment :folded_hands:

Actually, it’s a wrapper of those three functions to avoid repetition works.

wingyplus

wingyplus OP

Thanks for the comment. :folded_hands:

I just see that Zoi has a struct helper already (from @byu mentioned). Will refactoring to use those functions instead.

nulltree

nulltree

I’m so happy libraries like Zoi seem to catch on and inspire extension (infant adoption steps, but still).

They complement my way of thinking really well!

wingyplus

wingyplus OP

Update from the latest main. The defstructure is now changed to defstruct and you can embed the schema into defstruct directly.

The API also use Zoi.Struct under the hood. So the enforce keys and struct declaration is now align with the Zoi upstream.

wingyplus

wingyplus OP

Type composition is now working! You can use t() function to reference another struct.

wingyplus

wingyplus OP

The library is now published on Hex zoi_defstruct | Hex . Feel free to provide feedback, open issues, or pull requests.

charlieaten

charlieaten

Great work @wingyplus, this is some inspiring stuff.

One concern I had though with this approach is that having a defstruct-like DSL that looks like Kernel.defstruct but behaves differently can be confusing.

Your work inspired me to experiment with Sigil, a proof-of-concept DSL for defining nested structs and validating external data using Zoi:

defmodule Post do
  use Sigil.Schema

  schema do
    field :title, Zoi.string()

    field :image, Image do
      field :url, Zoi.string()
      field :blurhash, Zoi.string()

      field :metadata, Metadata do
        field :size, Zoi.integer() |> Zoi.optional()
        field :format, Zoi.string() |> Zoi.optional()
      end
    end
  end
end

I’m still iterating and may try more compact forms for types like:

field :age, :integer, coerce: true

This has been a great way to learn macros and DSL design, and aims to complement(and obviously heavily inspired by) Ecto. Whereas Ecto handles data mapping and persistence at the external data/application(and database) layer, validation libraries like zoi and the likes and thus Sigil aim to provide a layer that works great for things like wrapping external api’s into client libraries and doing validation and egornomic casting into elixir constructs.

Thanks again—I hope others find it interesting.

— All posts loaded —

Where Next? Top

Trending in Announcing Top

type1fool
WebAuthnLiveComponent WebAuthnComponents See this post about renaming the package. Passwordless authentication for Phoenix LiveView app...
New
GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
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
ahamez
Hi everyone, I’ve been working on this protobuf library for 3 years. We use it in the company I work for, EasyMile, to communicate with ...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
kip
I’ll shortly be launching Text, a nascent text analysis library. Current functionality In this early version (not ready for prime time) ...
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
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
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
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
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