SagaSaga
SagaJson

SagaJson

JSON library top-level: the Json opaque type, the shared Error type, and the decoder-running entry points.

For encoding, see SagaJson.Encode. For decoding primitives and combinators, see SagaJson.Decode.

Types

Json

opaque type Json

A JSON value. Opaque so the internal representation can evolve. Construct with SagaJson.Encode primitives; inspect with SagaJson.Decode combinators.

Error

type Error =
  | InvalidJson String
  | InvalidShape (expected: String) (found: String) (path: List String)

Error returned when JSON parsing or decoding fails.

NameStyle

type NameStyle =
  | AsIs
  | CamelCase
  | KebabCase
  | SnakeCase
  | ScreamingSnakeCase

How record field names and variant names are transformed before emission (encode) or matched against input (decode). Source convention is snake_case Saga identifiers (the type-level Symbol reflects the source name verbatim); rename_all is applied to that source name symmetrically on both directions.

TagFormat

type TagFormat =
  | ExternallyTagged
  | AdjacentlyTagged
  | InternallyTagged
  | Untagged

How sum-type variants are tagged in JSON.

  • ExternallyTagged (default): {"Variant": payload} for variants that carry a payload; unit variants emit as bare strings ("Admin") when unit_variants_as_strings is True (the default).
  • AdjacentlyTagged: {<tag_field>: "Variant", <content_field>: payload} — both fields always emitted, including for unit (U1) variants where content_field carries null.
  • InternallyTagged: tag merged into the payload object as <tag_field>. Only well-defined when the payload renders to a JSON object (single record-valued variants) or null (unit variants). For primitive / array payloads the encoder falls back to ExternallyTagged — same restriction as serde.
  • Untagged: emit the payload directly; variant identity is lost.

Options

record Options {
  rename_all: NameStyle,
  omit_nothing: Bool,
  tag_format: TagFormat,
  tag_field: String,
  content_field: String,
  unit_variants_as_strings: Bool
}

Uniform codec options. Shared between encode and decode so a single Options value drives a symmetric round-trip. Construct with record-update syntax: { default_options | rename_all: CamelCase }. Note: omit_nothing is encode-only (no-op on decode).

Traits

WithOptions

trait WithOptions a {
  fun map_options : Options -> Options -> a -> a
}

Types that carry an Options value internally and let you adjust it functionally. Implemented by SagaJson.Encode.Encoder and SagaJson.Decode.Decoder. The free-function setters (rename_keys, tag_format, ...) are written against this trait so they work on both builders.

Values

default_options

fun default_options : Options

The canonical defaults: no renaming, emit nulls for Maybe Nothing, externally-tagged sums with unit variants emitted as bare strings (matching serde, kotlinx.serialization, and most other modern JSON libraries). Set unit_variants_as_strings: False to recover the legacy {"Admin": null} shape (or use the as_tagged strategy).

Functions

from_value

fun from_value : Value -> Json

Wrap a Value as a Json. Library-internal; use SagaJson.Encode.

to_value

fun to_value : Json -> Value

Unwrap a Json to its underlying Value. Library-internal; use SagaJson.Decode for ordinary decoding.

rename_keys

fun rename_keys : NameStyle -> a -> a where {a: WithOptions}

Set the rename_all field on the builder's Options.

omit_nothing

fun omit_nothing : a -> a where {a: WithOptions}

Set omit_nothing: True on the builder's Options. Encode-only; no-op on the decode side.

with_tag_format

fun with_tag_format : TagFormat -> a -> a where {a: WithOptions}

Set the tag_format field on the builder's Options.

with_tag_field

fun with_tag_field : String -> a -> a where {a: WithOptions}

Set the tag_field name (used by AdjacentlyTagged / InternallyTagged).

with_content_field

fun with_content_field : String -> a -> a where {a: WithOptions}

Set the content_field name (used by AdjacentlyTagged).

with_unit_variants_as_strings

fun with_unit_variants_as_strings : Bool -> a -> a where {a: WithOptions}

Set the unit_variants_as_strings field. Pass False to recover the legacy {"Admin": null} wrapped shape; True is the default.

apply_name_style

fun apply_name_style : NameStyle -> String -> String

Apply a NameStyle transform to a Saga source identifier (snake_case by convention). Library-internal; called by both the encoder and the decoder so a single Options value drives a symmetric round-trip.

parse_string

fun parse_string : String -> Result Json Error

Parse a JSON string into a Json value, without applying a decoder.

run

fun run : Json -> a needs {Fail Error} -> Json -> Result a Error

Apply a decoder to an already-parsed Json value, returning a Result.

parse

fun parse : Json -> a needs {Fail Error} -> String -> Result a Error

Parse a JSON string and apply a decoder in one step.