///|
/// A location in a JSON document from which typed child lenses can be created.
pub struct ObjectLens {
priv lens : Lens[Map[String, Json]]
}
///|
/// A reusable typed accessor for one location in a JSON document.
pub struct Lens[T] {
priv pointer : Pointer
priv decoder : Decoder[T]
priv on_missing : (() -> T)?
}
///|
/// Returns an object lens positioned at the document root.
pub fn root() -> ObjectLens {
ObjectLens::{
lens: Lens::{
pointer: Pointer::root(),
decoder: object_decoder(),
on_missing: None,
},
}
}
///|
/// Returns an object lens positioned at a root property.
pub fn object(key : String) -> ObjectLens {
root().object(key)
}
///|
/// Returns an object lens positioned at a child property.
pub fn ObjectLens::object(self : ObjectLens, key : String) -> ObjectLens {
ObjectLens::{
lens: Lens::{
pointer: self.lens.pointer.key(key),
decoder: object_decoder(),
on_missing: None,
},
}
}
///|
/// Returns a string lens positioned at a child property.
pub fn ObjectLens::string(self : ObjectLens, key : String) -> Lens[String] {
Lens::{
pointer: self.lens.pointer.key(key),
decoder: string_decoder(),
on_missing: None,
}
}
///|
/// Returns a boolean lens positioned at a child property.
pub fn ObjectLens::bool(self : ObjectLens, key : String) -> Lens[Bool] {
Lens::{
pointer: self.lens.pointer.key(key),
decoder: bool_decoder(),
on_missing: None,
}
}
///|
/// Returns a finite-number lens positioned at a child property.
pub fn ObjectLens::number(self : ObjectLens, key : String) -> Lens[Double] {
Lens::{
pointer: self.lens.pointer.key(key),
decoder: number_decoder(),
on_missing: None,
}
}
///|
/// Returns an integer lens that delegates conversion to `Double::to_int`.
pub fn ObjectLens::int(self : ObjectLens, key : String) -> Lens[Int] {
Lens::{
pointer: self.lens.pointer.key(key),
decoder: int_decoder(),
on_missing: None,
}
}
///|
/// Returns a raw JSON lens positioned at a child property.
pub fn ObjectLens::json(self : ObjectLens, key : String) -> Lens[Json] {
Lens::{
pointer: self.lens.pointer.key(key),
decoder: json_decoder(),
on_missing: None,
}
}
///|
/// Returns a lens that decodes every array item with this lens's decoder.
pub fn[T] Lens::array(self : Lens[T]) -> Lens[Array[T]] {
Lens::{
pointer: self.pointer,
decoder: array_decoder(self.decoder),
on_missing: None,
}
}
///|
/// Returns `None` for JSON `null` while preserving missing-property errors.
pub fn[T] Lens::nullable(self : Lens[T]) -> Lens[T?] {
Lens::{
pointer: self.pointer,
decoder: nullable_decoder(self.decoder),
on_missing: None,
}
}
///|
/// Returns `None` for a missing selected path while rejecting JSON `null`.
pub fn[T] Lens::optional(self : Lens[T]) -> Lens[T?] {
Lens::{
pointer: self.pointer,
decoder: optional_decoder(self.decoder),
on_missing: Some(() => None),
}
}
///|
/// Returns `None` for either a missing selected path or JSON `null`.
pub fn[T] Lens::nullish(self : Lens[T]) -> Lens[T?] {
Lens::{
pointer: self.pointer,
decoder: nullable_decoder(self.decoder),
on_missing: Some(() => None),
}
}
///|
/// Reads this object lens from a JSON document.
pub fn ObjectLens::get(
self : ObjectLens,
document : Json,
) -> Map[String, Json] raise LensError {
self.lens.get(document)
}
///|
/// Reads and decodes this lens from a JSON document.
pub fn[T] Lens::get(self : Lens[T], document : Json) -> T raise LensError {
let selected = match lookup(document, self.pointer) {
Some(value) => value
None => {
match self.on_missing {
Some(on_missing) => return on_missing()
None => ()
}
raise LensError(Issue::{
pointer: self.pointer,
code: MissingProperty,
message: None,
})
}
}
self.decoder.decode(selected) catch {
DecodeProblem(pointer, code, message) =>
raise LensError(Issue::{
pointer: self.pointer.append(pointer),
code,
message,
})
}
}