Module

pooka/json/decode

src/pooka/json/decode.pooka

A 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.

Pooka
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

class

DecodeError

src/pooka/json/decode.pooka:23
class DecodeError(path: List(String), expected: String, found: String)

The address of a shape mismatch, from the outermost field to the innermost item.

field

path

src/pooka/json/decode.pooka:23
path: List(String)
INFERREDList(String)
field

expected

src/pooka/json/decode.pooka:23
expected: String
INFERREDString
field

found

src/pooka/json/decode.pooka:23
found: String
INFERREDString
constructor

new

src/pooka/json/decode.pooka:23
INFERREDfn(List(String), String, String) -> pooka/json/decode.DecodeError
class

ReadError

src/pooka/json/decode.pooka:26
class ReadError

Parsing and application decoding are different failures and remain distinct.

class

Syntax

src/pooka/json/decode.pooka:28
class Syntax(error: json.JsonError) is ReadError
field

error

src/pooka/json/decode.pooka:28
error: json.JsonError
constructor

new

src/pooka/json/decode.pooka:28
class

Shape

src/pooka/json/decode.pooka:30
class Shape(errors: List(DecodeError)) is ReadError
field

errors

src/pooka/json/decode.pooka:30
errors: List(DecodeError)
constructor

new

src/pooka/json/decode.pooka:30
class

Decoder

src/pooka/json/decode.pooka:33
class Decoder(a)

A reusable, checked recipe over Json values.

constructor

new

src/pooka/json/decode.pooka:36
new(read: fn(json.Json) -> Result(a, List(DecodeError)))
method

run

src/pooka/json/decode.pooka:41
run(value: json.Json) -> Result(a, List(DecodeError))
INFERREDfn(pooka/json.Json) -> Result(a, List(pooka/json/decode.DecodeError))

Decode a previously parsed value without reading the source text again.

method

map

src/pooka/json/decode.pooka:46
map(change: fn(a) -> b) -> Decoder(b)
INFERREDfn(fn(a) -> a) -> pooka/json/decode.Decoder(a)

Transform a checked result. The error branch leaves the callback asleep.

method

then

src/pooka/json/decode.pooka:54
then(next: fn(a) -> Decoder(b)) -> Decoder(b)

Select another recipe using a checked discriminator, then read the same Json.

method

check

src/pooka/json/decode.pooka:63
check(accept: fn(a) -> Bool, expected: String) -> Decoder(a)
INFERREDfn(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.

function

read

src/pooka/json/decode.pooka:75
read(text: String, decoder: Decoder(a)) -> Result(a, ReadError)
INFERREDfn(String, pooka/json/decode.Decoder(a)) -> Result(a, pooka/json/decode.ReadError)

Parse and decode an application value, preserving both failure categories.

function

read_with_limits

src/pooka/json/decode.pooka:83
read_with_limits(
  text: String,
  decoder: Decoder(a),
  max_bytes: Int,
  max_depth: Int
) -> Result(a, ReadError)
INFERREDfn(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.

function

string

src/pooka/json/decode.pooka:131
string() -> Decoder(String)
INFERREDfn() -> pooka/json/decode.Decoder(String)

Read text; numbers and booleans are not silently rendered into strings.

function

int

src/pooka/json/decode.pooka:141
int() -> Decoder(Int)
INFERREDfn() -> pooka/json/decode.Decoder(Int)

Read an arbitrary-precision JSON integer, preserving exactness.

function

float

src/pooka/json/decode.pooka:152
float() -> Decoder(Float)
INFERREDfn() -> 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.

function

bool

src/pooka/json/decode.pooka:162
bool() -> Decoder(Bool)
INFERREDfn() -> pooka/json/decode.Decoder(Bool)

Read one of JSON's two boolean values.

function

null

src/pooka/json/decode.pooka:172
null() -> Decoder(Nil)
INFERREDfn() -> pooka/json/decode.Decoder(Nil)

Read null as Nil. Absence and an empty array are separate values.

function

value

src/pooka/json/decode.pooka:182
value() -> Decoder(json.Json)

Keep a Json value unchanged, useful for an application's extension fields.

function

succeed

src/pooka/json/decode.pooka:187
succeed(answer: a) -> Decoder(a)
INFERREDfn(a) -> pooka/json/decode.Decoder(a)

Ignore the input and return a known checked value.

function

failure

src/pooka/json/decode.pooka:192
failure(expected: String) -> Decoder(a)
INFERREDfn(String) -> pooka/json/decode.Decoder(a)

Reject the input with an application-specific expectation.

function

field

src/pooka/json/decode.pooka:197
field(name: String, decoder: Decoder(a)) -> Decoder(a)

Read a required object field. Duplicate keys follow json.get: the first wins.

function

optional_field

src/pooka/json/decode.pooka:210
optional_field(name: String, decoder: Decoder(a)) -> Decoder(Option(a))
INFERREDfn(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.

function

optional

src/pooka/json/decode.pooka:226
optional(decoder: Decoder(a)) -> Decoder(Option(a))

Treat an explicit null as None, and decode every other value as Some.

function

at

src/pooka/json/decode.pooka:239
at(index: Int, decoder: Decoder(a)) -> Decoder(a)

Decode a zero-based array position. Negative and missing indexes return errors.

function

list

src/pooka/json/decode.pooka:254
list(decoder: Decoder(a)) -> Decoder(List(a))

Read every array item, collecting all errors in their input order.

function

one_of

src/pooka/json/decode.pooka:283
one_of(recipes: List(Decoder(a))) -> Decoder(a)

Try alternatives in order, retaining their errors when all fail.

function

map2

src/pooka/json/decode.pooka:309
map2(first: Decoder(a), second: Decoder(b), combine: fn(a, b) -> c) -> Decoder(
  c
)

Read two fields or positions from one input, then construct a checked value.

function

map3

src/pooka/json/decode.pooka:320
map3(
  first: Decoder(a),
  second: Decoder(b),
  third: Decoder(c),
  combine: fn(a, b, c) -> d
) -> Decoder(d)

Read three components. Stop at the first failing component.

function

lazy

src/pooka/json/decode.pooka:335
lazy(build: fn() -> Decoder(a)) -> Decoder(a)

Delay building a recipe until it sees a value, allowing recursive structures.

function

describe

src/pooka/json/decode.pooka:340
describe(error: ReadError) -> String
INFERREDfn(pooka/json/decode.ReadError) -> String

Describe structured errors using escaped JSON-pointer segments after $.