lens

    Typed JSON lenses, builders, and aggregate validation for MoonBit

    json
    lens
    validation
    moonbit
    Download zip
    Author
    Version
    0.4.3
    License
    MIT
    Last updated
    2 months ago
    Downloads
    1K

    No dependencies

    #lens

    totto2727/lens is a MoonBit module for typed JSON lenses, builders, and aggregate validation. The module publishes one lens package; see the detailed package README for checked examples and package-level usage.

    This document is canonical README.mbt.md; maintain README.md as the relative symlink README.md -> README.mbt.md.

    #Usage

    Add the module, then follow the package usage examples.

    moon add totto2727/lens@0.4.3

    #Key features

    • One publishable lens package for typed JSON traversal and construction.
    • Checked package examples for typed reads and JSON object building.
    • Generated public API documentation on Mooncakes.

    #Prerequisites

    #Setup

    1. Add totto2727/lens to a MoonBit project.

    moon add totto2727/lens@0.4.3

    1. Read the detailed package README for executable usage examples.

    #API

    The maintained public API index and generated signatures are published in the Mooncakes API reference.

    #Development

    For repository structure, validation commands, and contribution rules, see AGENTS.md.

    #License

    MIT. See LICENSE.

    This README was generated from the share-artifact skill and README template.

    #lens package

    Detailed usage for the totto2727/lens package: typed JSON lenses, builders, and aggregate validation for reusable, checked access to JSON documents.

    This document is the canonical literate package README; the repository module overview is ../README.mbt.md.

    #Usage

    Create typed child lenses once and reuse them across documents. A lens read reports a structured LensError with its JSON Pointer when traversal or decoding fails.

    ///|
    test {
    let document = @json.parse("{\"user\":{\"name\":\"Ada\",\"age\":37}}")
    let user = object("user")
    let name_lens = user.string("name")
    let age_lens = user.int("age")

    inspect(name_lens.get(document), content="Ada")
    inspect(age_lens.get(document), content="37")
    }

    Build a new JSON object through the same typed lenses.

    ///|
    test {
    let builder = JsonBuilder::JsonBuilder()
    let user = object("user")
    user.string("name").set(builder, "Ada")
    user.int("age").set(builder, 37)

    @json.json_inspect(builder, content={ "user": { "name": "Ada", "age": 37 } })
    }

    #Key features

    • Typed accessors for strings, booleans, numbers, integers, objects, arrays, custom FromJson/ToJson values, and raw Json.
    • Presence-aware reads and writes with distinct nullable, optional, and nullish semantics.
    • JsonBuilder construction with typed path-conflict errors and deterministic replacement/removal behavior.
    • Aggregate validate checks that preserve every failure in input order without constructing application values.
    • RFC 6901 pointers and standard JsonDecodeError path propagation for nested custom decoders.

    #Prerequisites

    #Setup

    1. Add the published module to a MoonBit project.

    moon add totto2727/lens@0.4.3

    1. Import the package as @lens and compose lenses from @lens.root() or @lens.object("property").

    #API

    The maintained public API index and generated signatures are published in the Mooncakes API reference.

    #Development

    For repository structure, validation commands, and contribution rules, see AGENTS.md.

    #License

    MIT. See LICENSE.

    This README was generated from the share-artifact skill and README template.

    LensTrait

    pub trait LensTrait {
    fn check(Self, Json) -> Unit raise LensError
    }

    A type-erased lens read used only for aggregate validation.

    Implementations intentionally discard successful decoded values. Use the original typed lenses to read values after validate returns Valid.

    JsonBuildError

    pub suberror JsonBuildError {
    JsonBuildError(JsonBuildIssue)
    } derive(Eq,
    Debug
    )

    The typed error raised when a lens cannot write a value to a JSON builder.

    LensError

    pub suberror LensError {
    LensError(Issue)
    } derive(Eq,
    Debug
    )

    The typed error raised when a lens cannot read its selected value.

    Decoder

    type Decoder[T]

    Encoder

    type Encoder[T]

    Issue

    pub struct Issue {
    pointer : Pointer
    code : IssueCode
    message : String?
    } derive(Eq,
    Debug
    )

    A structured diagnostic containing the exact pointer and failure reason.

    IssueCode

    pub enum IssueCode {
    MissingProperty
    TypeMismatch(expected~ : JsonKind, actual~ : JsonKind)
    IndexOutOfBounds(index~ : Int, length~ : Int)
    ConstraintViolation(code~ : String)
    ExternalDecode
    } derive(Eq,
    Debug
    )

    A machine-readable reason why a lens or validation check failed.

    JsonBuildIssue

    pub struct JsonBuildIssue {
    pointer : Pointer
    code : JsonBuildIssueCode
    } derive(Eq,
    Debug
    )

    A structured JSON construction failure at an exact output pointer.

    JsonBuildIssueCode

    pub enum JsonBuildIssueCode {
    PathConflict
    } derive(Eq,
    Debug
    )

    A machine-readable reason why a typed value could not be written to a JSON builder.

    JsonBuilder

    pub struct JsonBuilder {
    // private fields
    }

    A mutable object builder populated through typed lenses and serialized with ToJson.

    JsonBuilder::JsonBuilder

    fn JsonBuilder::JsonBuilder() -> JsonBuilder

    Creates an empty JSON object builder.

    test {
    let builder = JsonBuilder::JsonBuilder()
    object("user").string("name").set(builder, "Ada")
    @json.json_inspect(builder, content={ "user": { "name": "Ada" } })
    }

    JsonKind

    pub enum JsonKind {
    Null
    Boolean
    Number
    String
    Array
    Object
    } derive(Eq,
    Debug
    )

    The JSON value category used by structured lens diagnostics.

    Lens

    pub struct Lens[T] {
    // private fields
    }

    A reusable typed accessor for one location in a JSON document.

    A lens can be reused across documents. Its selected pointer is retained in diagnostics, including nested array indices and RFC 6901 key escaping.
    impl LensTrait for Lens[T]

    Lens::add_to_json_path

    Appends this lens's pointer to an existing JSON path.

    Lens::array

    fn[T] Lens::array(self : Lens[T]) -> Lens[Array[T]]

    Returns a lens that decodes every array item with this lens's decoder.

    Item failures include the zero-based item index in their diagnostic pointer.

    Lens::decode_from_json

    Selects raw JSON and delegates read-only decoding to standard FromJson.

    Lens::get

    fn[T] Lens::get(self : Lens[T], document : Json) -> T raise LensError

    Reads and decodes this lens from a JSON document.

    Lens::get_or_json_decode_error

    fn[T] Lens::get_or_json_decode_error(self : Lens[T], document : Json, path :
    JsonPath
    ) -> T raise
    JsonDecodeError

    Reads this lens and translates a lens failure into a standard JSON decode error.

    Lens::json_decode_error

    fn[T] Lens::json_decode_error(self : Lens[T], path :
    JsonPath
    , message : String) ->
    JsonDecodeError

    Creates a standard JSON decode error at this lens's location under an existing path.

    Lens::nullable

    fn[T] Lens::nullable(self : Lens[T]) -> PresenceLens[T]

    Returns None for JSON null while preserving missing-property errors.

    Lens::nullish

    fn[T] Lens::nullish(self : Lens[T], encode_mode? : NullishEncodeMode) -> PresenceLens[T]

    Returns None for either a missing selected path or JSON null.

    None is omitted by default. Pass encode_mode=Null to write JSON null instead.

    Lens::optional

    fn[T] Lens::optional(self : Lens[T]) -> PresenceLens[T]

    Returns None for a missing selected path while rejecting JSON null.

    Lens::set

    fn[T] Lens::set(self : Lens[T], builder : JsonBuilder, value : T) -> Unit raise JsonBuildError

    Writes a typed value at this lens's output pointer.

    Repeated writes to the same pointer use the latest value. Missing object parents are created. The builder is unchanged when a path conflict raises JsonBuildError.

    Lens::set_or_abort

    fn[T] Lens::set_or_abort(self : Lens[T], builder : JsonBuilder, value : T) -> Unit

    Writes a typed value for an infallible serialization contract.

    Use this from ToJson::to_json, whose trait signature cannot propagate JsonBuildError. A failure indicates a conflicting static output schema or another serializer implementation defect and aborts the process.

    NullishEncodeMode

    pub(all) enum NullishEncodeMode {
    Omit
    Null
    } derive(Eq,
    Debug
    )

    Controls how a nullish lens encodes None.

    ObjectLens

    pub struct ObjectLens {
    // private fields
    }

    A location in a JSON document from which typed child lenses can be created.

    Reading an object returns a copied top-level map, so mutations to that map do not change the source document. Nested Json values retain normal JSON sharing semantics.

    ObjectLens::bool

    fn ObjectLens::bool(self : ObjectLens, key : String) -> Lens[Bool]

    Returns a boolean lens positioned at a child property.

    ObjectLens::custom

    fn[T :
    FromJson
    + ToJson] ObjectLens::custom(self : ObjectLens, key : String) -> Lens[T]

    Returns a typed lens that delegates decoding and encoding to standard JSON traits.

    FromJson decode failures retain the selected JSON path, and ToJson supplies the corresponding builder encoding.

    ObjectLens::get

    fn ObjectLens::get(self : ObjectLens, document : Json) -> Map[String, Json] raise LensError

    Reads this object lens from a JSON document.

    ObjectLens::int

    fn ObjectLens::int(self : ObjectLens, key : String) -> Lens[Int]

    Returns an integer lens that delegates conversion to Double::to_int.

    Fractional, saturating, and special-value behavior therefore follows the standard MoonBit Double::to_int conversion.

    ObjectLens::json

    fn ObjectLens::json(self : ObjectLens, key : String) -> Lens[Json]

    Returns a raw JSON lens positioned at a child property.

    Use this when the selected value intentionally remains opaque Json. For application types with standard JSON traits, prefer custom.

    ObjectLens::number

    fn ObjectLens::number(self : ObjectLens, key : String) -> Lens[Double]

    Returns a number lens positioned at a child property.

    The retained JSON Double is returned without an additional finiteness check, including non-finite values.

    ObjectLens::object

    fn ObjectLens::object(self : ObjectLens, key : String) -> ObjectLens

    Returns an object lens positioned at a child property.

    ObjectLens::string

    fn ObjectLens::string(self : ObjectLens, key : String) -> Lens[String]

    Returns a string lens positioned at a child property.

    Pointer

    pub struct Pointer {
    // private fields
    } derive(Eq,
    Debug
    )

    An immutable JSON Pointer identifying a location in a JSON document.

    Pointer::to_string

    fn Pointer::to_string(self : Pointer) -> String

    Returns the RFC 6901 string representation of this pointer.

    PresenceLens

    pub struct PresenceLens[T] {
    // private fields
    }

    A typed accessor whose missing and null behavior can be replaced without nesting options.

    Every presence combinator returns this same T? shape. The last combinator call controls both decoding and encoding behavior.

    PresenceLens::add_to_json_path

    Appends this lens's pointer to an existing JSON path.

    PresenceLens::array

    fn[T] PresenceLens::array(self : PresenceLens[T]) -> Lens[Array[T?]]

    Returns a lens that treats every array item as nullable.

    This normalizes None to JSON null so array indices remain stable. It is different from applying optional to the whole array property.

    PresenceLens::get

    fn[T] PresenceLens::get(self : PresenceLens[T], document : Json) -> T? raise LensError

    Reads and decodes this presence-aware lens from a JSON document.

    PresenceLens::get_or_json_decode_error

    Reads this lens and translates a lens failure into a standard JSON decode error.

    PresenceLens::json_decode_error

    Creates a standard JSON decode error at this lens's location under an existing path.

    PresenceLens::nullable

    fn[T] PresenceLens::nullable(self : PresenceLens[T]) -> PresenceLens[T]

    Replaces the current presence policy with nullable semantics.

    PresenceLens::nullish

    fn[T] PresenceLens::nullish(self : PresenceLens[T], encode_mode? : NullishEncodeMode) -> PresenceLens[T]

    Replaces the current presence policy with nullish semantics.

    PresenceLens::optional

    fn[T] PresenceLens::optional(self : PresenceLens[T]) -> PresenceLens[T]

    Replaces the current presence policy with optional semantics.

    PresenceLens::set

    fn[T] PresenceLens::set(self : PresenceLens[T], builder : JsonBuilder, value : T?) -> Unit raise JsonBuildError

    Writes an optional typed value using this lens's current presence policy.

    nullable(None) and nullish(encode_mode=Null) write JSON null, while optional(None) and nullish(encode_mode=Omit) remove the selected value.

    PresenceLens::set_or_abort

    fn[T] PresenceLens::set_or_abort(self : PresenceLens[T], builder : JsonBuilder, value : T?) -> Unit

    Writes an optional typed value for an infallible serialization contract.

    Validation

    pub enum Validation {
    Valid
    Invalid(ReadOnlyArray[Issue])
    } derive(Eq,
    Debug
    )

    The outcome of validating a JSON document with type-erased checks.

    Valid carries no decoded value. Use the original typed lenses to read the document after validation succeeds.

    object

    fn object(key : String) -> ObjectLens

    Returns an object lens positioned at a root property.

    root

    fn root() -> ObjectLens

    Returns an object lens positioned at the document root.

    test {
    let document = @json.parse("{\"user\":{\"name\":\"Ada\"}}")
    inspect(object("user").string("name").get(document), content="Ada")
    }

    validate

    fn validate(document : Json, lenses : Array[&LensTrait]) -> Validation

    Runs every lens check and returns all issues in input order.

    This function never constructs or returns application values. An empty input is Valid; otherwise every failed read is retained in the returned Invalid value.

    test {
    let document = @json.parse("{\"user\":{\"name\":\"Ada\"}}")
    let name_lens = object("user").string("name")
    match validate(document, [name_lens]) {
    Valid => ()
    Invalid(_) => fail("expected valid document")
    }
    }

    Powered by MoonBit

    Site sourceReport issueModulesSkillsBuild queueStatistics

    © 2026 mooncakes.io