Customize outputs with Inspect protocol

I love to analyze changes that occur in programming languages that I use on a daily basis. Many of these changes can make your job much easier.

In this post, I would like to refer to the topic presented more than a year ago in the Global customize for inspect data in Elixir. I touched on a way to modify the representation of the data. This could be done by changing default_inspect_fun/1.

Inspect protocol

In Elixir we have Inspect protocol to convert internal Elixir data structures for presentation. This protocol can be used also in our structures.

Exclude selected fields

If we want to present our structures omitting selected fields, the effect can be achieved by using except. This allows us to indicate which fields we do not want to present. This can be convenient when hiding information such as a password or similar.

Thanks to this, we can also hide sensitive fields from the point of view of GDPR and all legal provisions.

Indication of what fields we want to present

Using only we can indicate which fields we want to be presented. This has the advantage over the previously indicated except that we do not have to worry about updating everything after adding a new field. Unfortunately, with large structures, we have to balance and choose what suits us best with the volatility of objects in the system.

Indication of changed fields only

With Elixir 1.14 we got another possibility. Although it may seem impractical, thanks to optional we can indicate the fields we want to be presented only if a value other than the default is indicated.

This is extremely useful as it allows you to reduce the number of fields presented. Only when information appears it will be presented to the user.

Changing the way information is presented

For our example we will use the StructTest module to show the differences between versions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  defmodule StructTestOnly do
    @derive {Inspect, only: [:id, :role]}
    defstruct [:id, :name, role: :owner]
  end

  iex(1)> %StructTestOnly{}
  #StructTestOnly<id: nil, role: :owner, ...>

  defmodule StructTestExcept do
    @derive {Inspect, except: [:id, :role]}
    defstruct [:id, :name, role: :owner]
  end

  iex(2)> %StructTestExcept{}
  #StructTestExcept<name: :nil, ...>

  defmodule StructTestOptional do
    @derive {Inspect, optional: [:role]}
    defstruct [:id, :name, role: :owner]
  end

  iex(3)> %StructTestOptional{}
  %StructTestOptional{id: nil, name: nil}

It is worth emphasizing the change in the last case. We no longer have a response as a String but as an Elixir structure! This is because with :only or :except being used to restrict fields, the struct will be printed using the #_struct_name<...> notation, as the struct can no longer be copied and pasted as valid Elixir code.

Get new posts and extra comments

You'll receive every new post with extra unpublished comments available only to the subscribers!

I won't send you spam. Unsubscribe at any time.