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 tolength - 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 at(
path: List(String),
decoder: fn(Dynamic) -> Result(a, List(DecodeError)),
) -> fn(Dynamic) -> Result(a, List(DecodeError))
Decode a value at a given key path. This decoder is permissive and will use
index
for any numeric string keys where possible.
pub fn base16(
dynamic: Dynamic,
) -> Result(BitArray, List(DecodeError))
Decode a string representing base16-encoded binary data into a BitArray
.
pub fn base64(
dynamic: Dynamic,
) -> Result(BitArray, List(DecodeError))
Decode a string representing base64-encoded binary data into a BitArray
.
pub fn base64_url_encoded(
dynamic: Dynamic,
) -> Result(BitArray, List(DecodeError))
Decode a string representing url-safe base64-encoded binary data into a
BitArray
.
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_object1(
constructor: fn(a) -> b,
field1: #(String, fn(Dynamic) -> Result(a, List(DecodeError))),
) -> fn(Dynamic) -> Result(b, List(DecodeError))
Decode an object with exactly one field into some value. If additional fields are present, decoding will fail and the additional fields will be reported in the error.
pub fn exact_object2(
constructor: fn(a, b) -> c,
field1: #(String, fn(Dynamic) -> Result(a, List(DecodeError))),
field2: #(String, fn(Dynamic) -> Result(b, List(DecodeError))),
) -> fn(Dynamic) -> Result(c, List(DecodeError))
Decode an object with exactly two fields into some value. If additional fields are present, decoding will fail and the additional fields will be reported in the error.
pub fn exact_object3(
constructor: fn(a, b, c) -> d,
field1: #(String, fn(Dynamic) -> Result(a, List(DecodeError))),
field2: #(String, fn(Dynamic) -> Result(b, List(DecodeError))),
field3: #(String, fn(Dynamic) -> Result(c, List(DecodeError))),
) -> fn(Dynamic) -> Result(d, List(DecodeError))
Decode an object with exactly three fields into some value. If additional fields are present, decoding will fail and the additional fields will be reported in the error.
pub fn exact_object4(
constructor: fn(a, b, c, d) -> e,
field1: #(String, fn(Dynamic) -> Result(a, List(DecodeError))),
field2: #(String, fn(Dynamic) -> Result(b, List(DecodeError))),
field3: #(String, fn(Dynamic) -> Result(c, List(DecodeError))),
field4: #(String, fn(Dynamic) -> Result(d, List(DecodeError))),
) -> fn(Dynamic) -> Result(e, List(DecodeError))
Decode an object with exactly four fields into some value. If additional fields are present, decoding will fail and the additional fields will be reported in the error.
pub fn exact_object5(
constructor: fn(a, b, c, d, e) -> f,
field1: #(String, fn(Dynamic) -> Result(a, List(DecodeError))),
field2: #(String, fn(Dynamic) -> Result(b, List(DecodeError))),
field3: #(String, fn(Dynamic) -> Result(c, List(DecodeError))),
field4: #(String, fn(Dynamic) -> Result(d, List(DecodeError))),
field5: #(String, fn(Dynamic) -> Result(e, List(DecodeError))),
) -> fn(Dynamic) -> Result(f, List(DecodeError))
Decode an object with exactly five fields into some value. If additional fields are present, decoding will fail and the additional fields will be reported in the error.
pub fn exact_object6(
constructor: fn(a, b, c, d, e, f) -> g,
field1: #(String, fn(Dynamic) -> Result(a, List(DecodeError))),
field2: #(String, fn(Dynamic) -> Result(b, List(DecodeError))),
field3: #(String, fn(Dynamic) -> Result(c, List(DecodeError))),
field4: #(String, fn(Dynamic) -> Result(d, List(DecodeError))),
field5: #(String, fn(Dynamic) -> Result(e, List(DecodeError))),
field6: #(String, fn(Dynamic) -> Result(f, List(DecodeError))),
) -> fn(Dynamic) -> Result(g, List(DecodeError))
Decode an object with exactly six fields into some value. If additional fields are present, decoding will fail and the additional fields will be reported in the error.
pub fn exact_set(
decoder: fn(Dynamic) -> Result(a, List(DecodeError)),
) -> fn(Dynamic) -> Result(Set(a), List(DecodeError))
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))
pub fn index(
idx: Int,
decoder: fn(Dynamic) -> Result(a, List(DecodeError)),
) -> fn(Dynamic) -> Result(a, List(DecodeError))
Decode a value at a given index. This decoder is permissive and will try to decode tuples, objects with string integer keys, and in the worst case will decode a list and index into that.
For strict tuple access, use the element
decoder from the standard library.
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 keys(
dynamic: Dynamic,
) -> Result(List(String), List(DecodeError))
Decode just the keys of an object as a list of strings.
pub fn non_empty_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 non_empty_string(
dynamic: Dynamic,
) -> Result(String, List(DecodeError))
This decoder will decode a string and then confirm that it is not empty.
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 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 semver(
dynamic: Dynamic,
) -> Result(Version, List(DecodeError))
Decode a string representing a valid semantic version into a Version
value from the stoiridh_version package.
pub fn set(
decoder: fn(Dynamic) -> Result(a, List(DecodeError)),
) -> fn(Dynamic) -> Result(Set(a), List(DecodeError))
pub fn tagged_union(
tag: 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),
[
#("wibble", dynamic.decode1(Wibble, dynamic.field("foo", dynamic.int))),
#("wobble", dynamic.decode1(Wobble, dynamic.field("bar", dynamic.string))),
]
)(dynamic)
}
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))
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)
}