///|
priv suberror DecodeProblem {
Structured(pointer~ : Pointer, code~ : IssueCode, message~ : String?)
External(pointer~ : Pointer, error~ : @json.JsonDecodeError)
}
///|
struct Decoder[T] {
decode_ : (Json, @json.JsonPath?) -> T raise DecodeProblem
}
///|
fn[T] Decoder::decode(
self : Decoder[T],
value : Json,
path : @json.JsonPath?,
) -> T raise DecodeProblem {
(self.decode_)(value, path)
}
///|
fn type_mismatch(expected : JsonKind, value : Json) -> DecodeProblem {
Structured(
pointer=Pointer::root(),
code=IssueCode::TypeMismatch(expected~, actual=json_kind(value)),
message=None,
)
}
///|
fn string_decoder() -> Decoder[String] {
Decoder::{
decode_: fn(value, _path) -> String raise DecodeProblem {
match value {
Json::String(value) => value
_ => raise type_mismatch(JsonKind::String, value)
}
},
}
}
///|
fn bool_decoder() -> Decoder[Bool] {
Decoder::{
decode_: fn(value, _path) -> 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, _path) -> Double raise DecodeProblem {
match value {
Json::Number(number, ..) => number
_ => raise type_mismatch(JsonKind::Number, value)
}
},
}
}
///|
fn int_decoder() -> Decoder[Int] {
Decoder::{
decode_: fn(value, _path) -> 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, _path) { value } }
}
///|
fn object_decoder() -> Decoder[Map[String, Json]] {
Decoder::{
decode_: fn(value, _path) -> Map[String, Json] raise DecodeProblem {
match value {
Json::Object(properties) => properties.copy()
_ => raise type_mismatch(JsonKind::Object, value)
}
},
}
}
///|
fn[T : @json.FromJson] custom_decoder() -> Decoder[T] {
Decoder::{
decode_: fn(value, path) -> T raise DecodeProblem {
@json.from_json(value, path?) catch {
error => raise External(pointer=Pointer::root(), error~)
}
},
}
}
///|
fn[T] array_decoder(item_decoder : Decoder[T]) -> Decoder[Array[T]] {
Decoder::{
decode_: fn(value, path) -> Array[T] raise DecodeProblem {
match value {
Json::Array(items) =>
items.mapi((index, item) => {
let item_path = match path {
Some(path) => Some(path.add_index(index))
None => None
}
item_decoder.decode(item, item_path) catch {
Structured(pointer~, code~, message~) =>
raise Structured(
pointer=pointer.prepend_index(index),
code~,
message~,
)
External(pointer~, error~) =>
raise External(pointer=pointer.prepend_index(index), error~)
}
})
_ => raise type_mismatch(JsonKind::Array, value)
}
},
}
}
///|
fn[T] nullable_decoder(decoder : Decoder[T]) -> Decoder[T?] {
Decoder::{
decode_: fn(value, path) -> T? raise DecodeProblem {
match value {
Json::Null => None
_ => Some(decoder.decode(value, path))
}
},
}
}
///|
fn DecodeProblem::json_decode_error(
self : DecodeProblem,
path : @json.JsonPath,
) -> @json.JsonDecodeError {
match self {
Structured(pointer~, code~, message~) => {
let issue = Issue::{ pointer, code, message }
pointer.json_decode_error(path, repr(LensError(issue)))
}
External(error~, pointer=_) => error
}
}