decode

Types

Decoder

pub type Decoder(a) {
  Decoder(fn(Dynamic) -> Result(a, String))
}

Constructors

  • Decoder(fn(Dynamic) -> Result(a, String))

Functions

atom

pub fn atom() -> Decoder(Atom)

Create a decoder that will attempt to transform a Dynamic into an Atom.

Note that in Erlang, values such as undefined, null, nil, and none are all atoms! In Elixir, nil is an atom as well.

atom_field

pub fn atom_field(
  named: String,
  with decoder: Decoder(a),
) -> Decoder(a)

Create a decoder that takes a field name as a string and tries to turn it into an atom in order to access it. If the atom doesn't exist, the field doesn't either! And in that case the decoder will fail.

Atoms are commonly used as map fields in Erlang and Elixir; when accessing map keys that are atoms, this saves you the trouble of having to handle atom creation/error handling yourself.

bool

pub fn bool() -> Decoder(Bool)

Create a decoder that will attempt to transform a Dynamic into a Bool.

decode_dynamic

pub fn decode_dynamic(
  dynamic: Dynamic,
  with decoder: Decoder(a),
) -> Result(a, String)

Perform the actual decoding! Attempt turn some Dynamic data into the type of Gleam data specified by your decoder.

dynamic

pub fn dynamic() -> Decoder(Dynamic)

Create a decoder that always succeeds with the Dynamic data provided, untouched.

This is useful when you are receiving particularly complex Dynamic data that you want to deal with later in your program (this might be useful when interfacing with Erlang or Elixir libraries, for example), or when you're going to send it back out to Erlang or Elixir code and aren't concerned about dealing with its structure in Gleam.

element

pub fn element(
  at position: Int,
  with decoder: Decoder(a),
) -> Decoder(a)

Create a decoder that retrieves an element in a tuple at the given position.

fail

pub fn fail(error: String) -> Decoder(a)

Create a decoder that always fails with the given value, ignoring the provided Dynamic data.

This is usually used with then and one_of.

field

pub fn field(named: a, with decoder: Decoder(b)) -> Decoder(a)

Create a decoder that gets the value for a given field in a map. If the field you're trying to access is an atom, consider using the atom_field function instead of this one.

float

pub fn float() -> Decoder(Float)

Create a decoder that will attempt to transform a Dynamic into a Float.

from_result

pub fn from_result(result: Result(a, String)) -> Decoder(a)

Create a decoder from a Result. Useful whenn used with then to transform a Dynamic value into a record/type.

int

pub fn int() -> Decoder(Int)

Create a decoder that will attempt to transform a Dynamic into an Int.

list

pub fn list(with decoder: Decoder(a)) -> Decoder(List(a))

Create a decoder for decoding a list of values.

map

pub fn map(
  fun: fn(a) -> b,
  with decoder: Decoder(a),
) -> Decoder(a)

Create a decoder that, if successful, transforms the original value it was decoding into a different value.

Use map rather than then when your transformation function will never fail (that is, when it returns a val, rather than a Result(val, err). Use then when it might!

map2

pub fn map2(
  fun: fn(a, b) -> c,
  decoder1: Decoder(a),
  decoder2: Decoder(b),
) -> Decoder(a)

Create a decoder from two decoders that, if both are successful, transforms those decoded values into a different value.

map2 and its siblings (map3, map4, etc.) are usually used to transform data such as Erlang records or Elixir maps into Gleam records/types.

map3

pub fn map3(
  fun: fn(a, b, c) -> d,
  decoder1: Decoder(a),
  decoder2: Decoder(b),
  decoder3: Decoder(c),
) -> Decoder(a)

map4

pub fn map4(
  fun: fn(a, b, c, d) -> e,
  decoder1: Decoder(a),
  decoder2: Decoder(b),
  decoder3: Decoder(c),
  decoder4: Decoder(d),
) -> Decoder(a)

map5

pub fn map5(
  fun: fn(a, b, c, d, e) -> f,
  decoder1: Decoder(a),
  decoder2: Decoder(b),
  decoder3: Decoder(c),
  decoder4: Decoder(d),
  decoder5: Decoder(e),
) -> Decoder(a)

map6

pub fn map6(
  fun: fn(a, b, c, d, e, f) -> g,
  decoder1: Decoder(a),
  decoder2: Decoder(b),
  decoder3: Decoder(c),
  decoder4: Decoder(d),
  decoder5: Decoder(e),
  decoder6: Decoder(f),
) -> Decoder(a)

map7

pub fn map7(
  fun: fn(a, b, c, d, e, f, g) -> h,
  decoder1: Decoder(a),
  decoder2: Decoder(b),
  decoder3: Decoder(c),
  decoder4: Decoder(d),
  decoder5: Decoder(e),
  decoder6: Decoder(f),
  decoder7: Decoder(g),
) -> Decoder(a)

map8

pub fn map8(
  fun: fn(a, b, c, d, e, f, g, h) -> i,
  decoder1: Decoder(a),
  decoder2: Decoder(b),
  decoder3: Decoder(c),
  decoder4: Decoder(d),
  decoder5: Decoder(e),
  decoder6: Decoder(f),
  decoder7: Decoder(g),
  decoder8: Decoder(h),
) -> Decoder(a)

ok_error_tuple

pub fn ok_error_tuple(
  ok_decoder: Decoder(a),
  error_decoder: Decoder(a),
) -> Decoder(a)

A common pattern in Erlang and Elixir code is to, instead of raising a runtime error upon some function's anticipated failure (resulting from something like bad arguments, or a failed database query or network request), return an {ok, Success} or {error, Failure} tuple (which would look like {:ok, success} or {:error, Failure} in Elixir) instead.

This function creates a decoder that addresses this common scenario by either running the ok_decoder if the Dynamic is a tuple whose first element is an ok atom, or the error_decoder if the Dynamic is a tuple whose first element is an error atom.

one_of

pub fn one_of(decoders: List(Decoder(a))) -> Decoder(a)

Create a decoder that tries to decode a value with a list of different decoders.

string

pub fn string() -> Decoder(String)

Create a decoder that will attempt to transform a Dynamic into a String.

succeed

pub fn succeed(a: a) -> Decoder(a)

Create a decoder that always succeeds with the given value, ignoring the provided Dynamic data.

This is usually used with then and one_of.

then

pub fn then(
  after decoder: Decoder(a),
  apply fun: fn(a) -> Decoder(b),
) -> Decoder(a)

Create a decoder that operates on a previous result. Often used with from_result to decode a Dynamic value into a particular record/type.