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 days ago
Downloads
656

#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 issuePackagesBuild queueSkillsStatistics

© 2026 mooncakes.io