decipher

Functions

pub fn all(
  decoders: List(fn(Dynamic) -> Result(a, List(DecodeError))),
) -> fn(Dynamic) -> Result(List(a), List(DecodeError))

Create a decoder for a list of values from a list of decoders to run. Each decoder will run against the input value, and all must succeed for the decoder to succeed.

Errors from each decoder will be collected, which means the entire list is run even if one decoder fails!

pub fn arraylike(
  decoder: fn(Dynamic) -> Result(a, List(DecodeError)),
) -> fn(Dynamic) -> Result(List(a), List(DecodeError))

In JavaScript certain objects are said to be “arraylike”. These are objects that satisfy the following conditions:

  • They have a length property that is a non-negative integer.
  • They have a property for each integer index from 0 up to length - 1.

Operations like document.querySelectorAll or document.getElementsByTagName return arraylike objects like a NodeList. This decoder is capable of decoding such objects into a proper Gleam List.

pub fn bool_string(
  dynamic: Dynamic,
) -> Result(Bool, List(DecodeError))

Decode a string that represents a YAML-style boolean value. Any of the following values will be decoded as True:

  • “true”
  • “True”
  • “on”
  • “On”
  • “yes”
  • “Yes”

Any of the following values will be decoded as False:

  • “false”
  • “False”
  • “off”
  • “Off”
  • “no”
  • “No”

Anything else will fail to decode.

pub fn enum(
  variants: List(#(String, a)),
) -> fn(Dynamic) -> Result(a, List(DecodeError))

A simplified version of the tagged_union decoder. First decodes a string, and then attempts to find a corresponding value from a list of variants.

This is how the bool_string decoder is implemented:

import decipher
import gleam/dynamic.{type DecodeError, type Decoder, type Dynamic, DecodeError}

pub fn bool_string(dynamic: Dynamic) -> Result(Bool, List(DecodeError)) {
  decipher.enum([
    #("true", True),
    #("True", True),
    #("on", True),
    #("On", True),
    #("yes", True),
    #("Yes", True),
    #("false", False),
    #("False", False),
    #("off", False),
    #("Off", False),
    #("no", False),
    #("No", False),
  ])(dynamic)
}
pub fn exact_set(
  decoder: fn(Dynamic) -> Result(a, List(DecodeError)),
) -> fn(Dynamic) -> Result(Set(a), List(DecodeError))

Decode a list or arraylike into a Set. This decoder is slightly slower than the set decoder, but it will guarantee that there were no duplicate values in the incoming list.

pub fn float_string(
  dynamic: Dynamic,
) -> Result(Float, List(DecodeError))

Decode a Float that has been converted to a string. Some JSON APIs will send numbers as strings, so this decoder can come in handy more often than you’d think!

pub fn http_date(
  dynamic: Dynamic,
) -> Result(Time, List(DecodeError))

Decode a string representing a HTTP-date as a Time value from the birl package.

pub fn int_string(
  dynamic: Dynamic,
) -> Result(Int, List(DecodeError))

Decode an Int that has been converted to a string. Some JSON APIs will send numbers as strings, so this decoder can come in handy more often than you’d think!

pub fn iso_8601(
  dynamic: Dynamic,
) -> Result(Time, List(DecodeError))

Decode a string representing an ISO 8601 datetime as a Time value from the birl package.

pub fn json_string(
  decoder: fn(Dynamic) -> Result(a, List(DecodeError)),
) -> fn(Dynamic) -> Result(a, List(DecodeError))

Occasionally you might find yourself in the situation where a JSON string is embedded in the dynamic value you’re trying to decode. This decoder lets you extract that JSON and then run the decoder against it.

pub fn non_negative_int(
  dynamic: Dynamic,
) -> Result(Int, List(DecodeError))

Decode an Int as long as it is greater than or equal to zero.

pub fn nonempty_list(
  decode: fn(Dynamic) -> Result(a, List(DecodeError)),
) -> fn(Dynamic) -> Result(List(a), List(DecodeError))

Decode a list or arraylike with at least one item into a List. If the incoming list is empty, decoding will fail.

pub fn nonempty_string(
  dynamic: Dynamic,
) -> Result(String, List(DecodeError))

This decoder will decode a string and then confirm that it is not empty.

pub fn number(
  dynamic: Dynamic,
) -> Result(Float, List(DecodeError))

This decoder is capable of decoding both Int and Float values. If the value is an Int, it will be converted to a Float automatically.

pub fn number_string(
  dynamic: Dynamic,
) -> Result(Float, List(DecodeError))

Decode numbers that have been converted to strings. This decoder is capable of decoding both Int and Float values converted to strings. Some JSON APIs will send numbers as strings, so this decoder can come in handy more often than you’d think!

pub fn set(
  decoder: fn(Dynamic) -> Result(a, List(DecodeError)),
) -> fn(Dynamic) -> Result(Set(a), List(DecodeError))

Decode a list or arraylike into a Set. Any duplicate values will be dropped. If you want to ensure that there are no duplicates, use the exact_set decoder instead.

pub fn tagged_union(
  tag_decoder: fn(Dynamic) -> Result(a, List(DecodeError)),
  variants: List(
    #(a, fn(Dynamic) -> Result(b, List(DecodeError))),
  ),
) -> fn(Dynamic) -> Result(b, List(DecodeError))

There is no standard way to represent something like Gleam’s custom types as JSON or YAML (or most common formats). It’s common then to represent them as a tagged or discriminated union where a field is used to signify which variant of the type is being represented.

This decoder lets you decode things in this format by first decoding the tag and then selecting the appropriate decoder to run based on that tag.

import decipher
import gleam/dynamic.{type DecodeError, type Decoder, type Dynamic, DecodeError}

type Example {
  Wibble(foo: Int)
  Wobble(bar: String)
}

fn example_decoder(dynamic: Dynamic) -> Result(Example, List(DecodeError)) {
  decipher.tagged_union(
    dynamic.field("$", dynamic.string),
    [
      dynamic.decode1(Wibble, dynamic.field("foo", dynamic.int)),
      dynamic.decode1(Wobble, dynamic.field("bar", dynamic.string)),
    ]
  )
}
pub fn unix_timestamp(
  dynamic: Dynamic,
) -> Result(Time, List(DecodeError))

Decode a Unix timestamp as a Time value from the birl package.

pub fn uri(dynamic: Dynamic) -> Result(Uri, List(DecodeError))

Decode a string representing a URI into a Gleam Uri value.

pub fn when(
  decoder: fn(Dynamic) -> Result(a, List(DecodeError)),
  is predicate: fn(a) -> Bool,
) -> fn(Dynamic) -> Result(a, List(DecodeError))

Run a decoder but only keep the result if it satisfies the given predicate. This is how decoders like non_negative_int can be implemented:

import decipher
import gleam/dynamic.{type DecodeError, type Decoder, type Dynamic, DecodeError}

pub fn non_negative_int(dynamic: Dynamic) -> Result(Int, List(DecodeError)) {
  decipher.when(dynamic.int, is: fn(x) { x >= 0 })(dynamic)
}
Search Document