Module
pooka/json/decode
src/pooka/json/decode.pookaA JSON shape is not yet an application value. This is the second promise. Decoders inspect the closed Json family and produce checked values, never reinterpret a foreign tuple as a class. Required fields and array positions keep their full paths. Objects retain the parser's first-key-wins lookup; optional fields distinguish absence from a present null value.
class Person(name: String, age: Int)
let person = decode.map2(decode.field("name", decode.string()), decode.field("age", decode.int()), Person)
let assert Ok(value) = decode.read("{\"name\":\"Ada\",\"age\":3}", person)
API reference
- classDecodeError
- classReadError
- classSyntax
- classShape
- classDecoder
- functionread
- functionread_with_limits
- functionstring
- functionint
- functionfloat
- functionbool
- functionnull
- functionvalue
- functionsucceed
- functionfailure
- functionfield
- functionoptional_field
- functionoptional
- functionat
- functionlist
- functionone_of
- functionmap2
- functionmap3
- functionlazy
- functiondescribe
class DecodeError(path: List(String), expected: String, found: String)
The address of a shape mismatch, from the outermost field to the innermost item.
path: List(String)
List(String)expected: String
Stringfound: String
String
fn(List(String), String, String) -> pooka/json/decode.DecodeErrorclass ReadError
Parsing and application decoding are different failures and remain distinct.
class Syntax(error: json.JsonError) is ReadError
error: json.JsonError
pooka/json.JsonError
fn(pooka/json.JsonError) -> pooka/json/decode.Syntaxclass Shape(errors: List(DecodeError)) is ReadError
errors: List(DecodeError)
List(pooka/json/decode.DecodeError)
fn(List(pooka/json/decode.DecodeError)) -> pooka/json/decode.Shapeclass Decoder(a)
A reusable, checked recipe over Json values.
new(read: fn(json.Json) -> Result(a, List(DecodeError)))
fn(fn(pooka/json.Json) -> Result(a, List(pooka/json/decode.DecodeError))) -> pooka/json/decode.Decoder(a)run(value: json.Json) -> Result(a, List(DecodeError))
fn(pooka/json.Json) -> Result(a, List(pooka/json/decode.DecodeError))Decode a previously parsed value without reading the source text again.
map(change: fn(a) -> b) -> Decoder(b)
fn(fn(a) -> a) -> pooka/json/decode.Decoder(a)Transform a checked result. The error branch leaves the callback asleep.
then(next: fn(a) -> Decoder(b)) -> Decoder(b)
fn(fn(a) -> pooka/json/decode.Decoder(a)) -> pooka/json/decode.Decoder(a)Select another recipe using a checked discriminator, then read the same Json.
check(accept: fn(a) -> Bool, expected: String) -> Decoder(a)
fn(fn(a) -> Bool, String) -> pooka/json/decode.Decoder(a)Apply a domain predicate after shape validation. Used inside field, the containing field supplies the error path automatically.
read(text: String, decoder: Decoder(a)) -> Result(a, ReadError)
fn(String, pooka/json/decode.Decoder(a)) -> Result(a, pooka/json/decode.ReadError)Parse and decode an application value, preserving both failure categories.
read_with_limits(
text: String,
decoder: Decoder(a),
max_bytes: Int,
max_depth: Int
) -> Result(a, ReadError)
fn(String, pooka/json/decode.Decoder(a), Int, Int) -> Result(a, pooka/json/decode.ReadError)Parse with byte/depth limits before applying the same checked recipe.
string() -> Decoder(String)
fn() -> pooka/json/decode.Decoder(String)Read text; numbers and booleans are not silently rendered into strings.
int() -> Decoder(Int)
fn() -> pooka/json/decode.Decoder(Int)Read an arbitrary-precision JSON integer, preserving exactness.
float() -> Decoder(Float)
fn() -> pooka/json/decode.Decoder(Float)Read a JSON float or explicitly convert an integer, as json.as_float does. Integer conversion may round; use int when exactness is required.
bool() -> Decoder(Bool)
fn() -> pooka/json/decode.Decoder(Bool)Read one of JSON's two boolean values.
null() -> Decoder(Nil)
fn() -> pooka/json/decode.Decoder(Nil)Read null as Nil. Absence and an empty array are separate values.
value() -> Decoder(json.Json)
fn() -> pooka/json/decode.Decoder(pooka/json.Json)Keep a Json value unchanged, useful for an application's extension fields.
succeed(answer: a) -> Decoder(a)
fn(a) -> pooka/json/decode.Decoder(a)Ignore the input and return a known checked value.
failure(expected: String) -> Decoder(a)
fn(String) -> pooka/json/decode.Decoder(a)Reject the input with an application-specific expectation.
field(name: String, decoder: Decoder(a)) -> Decoder(a)
fn(String, pooka/json/decode.Decoder(a)) -> pooka/json/decode.Decoder(a)Read a required object field. Duplicate keys follow json.get: the first wins.
optional_field(name: String, decoder: Decoder(a)) -> Decoder(Option(a))
fn(String, pooka/json/decode.Decoder(a)) -> pooka/json/decode.Decoder(Option(a))Treat a missing object field as None. A present null still goes to the recipe.
optional(decoder: Decoder(a)) -> Decoder(Option(a))
fn(pooka/json/decode.Decoder(a)) -> pooka/json/decode.Decoder(Option(a))Treat an explicit null as None, and decode every other value as Some.
at(index: Int, decoder: Decoder(a)) -> Decoder(a)
fn(Int, pooka/json/decode.Decoder(a)) -> pooka/json/decode.Decoder(a)Decode a zero-based array position. Negative and missing indexes return errors.
list(decoder: Decoder(a)) -> Decoder(List(a))
fn(pooka/json/decode.Decoder(a)) -> pooka/json/decode.Decoder(List(a))Read every array item, collecting all errors in their input order.
one_of(recipes: List(Decoder(a))) -> Decoder(a)
fn(List(pooka/json/decode.Decoder(a))) -> pooka/json/decode.Decoder(a)Try alternatives in order, retaining their errors when all fail.
map2(first: Decoder(a), second: Decoder(b), combine: fn(a, b) -> c) -> Decoder(
c
)
fn(pooka/json/decode.Decoder(a), pooka/json/decode.Decoder(b), fn(a, b) -> c) -> pooka/json/decode.Decoder(c)Read two fields or positions from one input, then construct a checked value.
map3(
first: Decoder(a),
second: Decoder(b),
third: Decoder(c),
combine: fn(a, b, c) -> d
) -> Decoder(d)
fn(pooka/json/decode.Decoder(a), pooka/json/decode.Decoder(b), pooka/json/decode.Decoder(c), fn(a, b, c) -> d) -> pooka/json/decode.Decoder(d)Read three components. Stop at the first failing component.
lazy(build: fn() -> Decoder(a)) -> Decoder(a)
fn(fn() -> pooka/json/decode.Decoder(a)) -> pooka/json/decode.Decoder(a)Delay building a recipe until it sees a value, allowing recursive structures.
describe(error: ReadError) -> String
fn(pooka/json/decode.ReadError) -> StringDescribe structured errors using escaped JSON-pointer segments after $.