///|
priv suberror DecodeProblem {
DecodeProblem(Pointer, IssueCode, String?)
}
///|
struct Decoder[T] {
decode_ : (Json) -> T raise DecodeProblem
}
///|
fn[T] Decoder::decode(self : Decoder[T], value : Json) -> T raise DecodeProblem {
(self.decode_)(value)
}
///|
fn type_mismatch(expected : JsonKind, value : Json) -> DecodeProblem {
DecodeProblem(
Pointer::root(),
IssueCode::TypeMismatch(expected~, actual=json_kind(value)),
None,
)
}
///|
fn string_decoder() -> Decoder[String] {
Decoder::{
decode_: fn(value) -> String raise DecodeProblem {
match value {
Json::String(value) => value
_ => raise type_mismatch(JsonKind::String, value)
}
},
}
}
///|
fn bool_decoder() -> Decoder[Bool] {
Decoder::{
decode_: fn(value) -> Bool raise DecodeProblem {
match value {
Json::True => true
Json::False => false
_ => raise type_mismatch(JsonKind::Boolean, value)
}
},
}
}
///|
fn number_decoder() -> Decoder[Double] {
Decoder::{
decode_: fn(value) -> Double raise DecodeProblem {
match value {
Json::Number(number, ..) => number
_ => raise type_mismatch(JsonKind::Number, value)
}
},
}
}
///|
fn int_decoder() -> Decoder[Int] {
Decoder::{
decode_: fn(value) -> Int raise DecodeProblem {
match value {
Json::Number(number, ..) => number.to_int()
_ => raise type_mismatch(JsonKind::Number, value)
}
},
}
}
///|
fn json_decoder() -> Decoder[Json] {
Decoder::{ decode_: fn(value) { value } }
}
///|
fn object_decoder() -> Decoder[Map[String, Json]] {
Decoder::{
decode_: fn(value) -> Map[String, Json] raise DecodeProblem {
match value {
Json::Object(properties) => properties.copy()
_ => raise type_mismatch(JsonKind::Object, value)
}
},
}
}
///|
fn[T] array_decoder(item_decoder : Decoder[T]) -> Decoder[Array[T]] {
Decoder::{
decode_: fn(value) -> Array[T] raise DecodeProblem {
match value {
Json::Array(items) =>
items.mapi((index, item) => {
item_decoder.decode(item) catch {
DecodeProblem(pointer, code, message) =>
raise DecodeProblem(pointer.prepend_index(index), code, message)
}
})
_ => raise type_mismatch(JsonKind::Array, value)
}
},
}
}
///|
fn[T] nullable_decoder(decoder : Decoder[T]) -> Decoder[T?] {
Decoder::{
decode_: fn(value) -> T? raise DecodeProblem {
match value {
Json::Null => None
_ => Some(decoder.decode(value))
}
},
}
}