src/JsonAdapter.bend source
src/JsonAdapter.bend on the hub · documented module
import Baseimport bend-kit-json@0.3.0.0/json.bend as Json# Sole owner of JSON operations. Consumers import THIS module for all# encode/parse/get work; they import the kit package ONLY for the Val type in# annotations (Bend cannot alias types across modules — same convention as# MyLsmStore.Sess).# TRUST BOUNDARY: Json.parse is structural recursion. Json.encode is @unsafe# upstream (work-list walk, documented in kit source); canonical-bytes# (equal content => identical text) is covered by json_bytes_probe and the# differential check vs Python json, not by proof. If kit ships a safe# encoder, only this file changes.# Wraps text as a JSON string value.def make_str(+text: String) -> Json.Val: Json.Str{text}# Wraps a value list as a JSON array.def make_arr(items: List<&2, Json.Val>) -> Json.Val: Json.Arr{items}# Builds one object field pair.def make_kv(+field_key: String, field_value: Json.Val) -> Sigma<&2, &2, String, _ => Json.Val>: (field_key, field_value)# Inserts one field pair into the map.def fold_pair(field_map: Map<&2, Json.Val>, field_pair: Sigma<&2, &2, String, _ => Json.Val>) -> Map<&2, Json.Val>: match field_pair: case (field_key, field_value): Map.set(&2, Json.Val, field_map, field_key, field_value)# Folds a field list into a map; the list shrinks first.def fold_fields(remaining_fields: List<&2, Sigma<&2, &2, String, _ => Json.Val>>, field_map: Map<&2, Json.Val>) -> Map<&2, Json.Val>: match remaining_fields: case Nil{}: field_map case Con{field_pair, tail_fields}: fold_fields(tail_fields, fold_pair(field_map, field_pair))# Builds an object; keys come out sorted by construction.def make_obj(fields: List<&2, Sigma<&2, &2, String, _ => Json.Val>>) -> Json.Val: Json.Obj{fold_fields(fields, Map.new(&2, Json.Val))}# Parses stored text; None on malformed input.def parse_text(+stored_text: String) -> Maybe<&2, Json.Val>: Json.parse(stored_text)# Looks up an object field; None when absent or not an object.def get_field(+document: Json.Val, +field_name: String) -> Maybe<&2, Json.Val>: Json.get(document, field_name)# Unwraps a string value; None otherwise.def as_str(json_value: Json.Val) -> Maybe<&2, String>: match json_value: case Json.Str{text}: Some{text} case _: None{}# Unwraps an array value; None otherwise.def as_arr(json_value: Json.Val) -> Maybe<&2, List<&2, Json.Val>>: match json_value: case Json.Arr{items}: Some{items} case _: None{}# Encodes with keys sorted; the canonical bytes.def encode_canonical(+document: Json.Val) -> String: Json.encode(document)