~/bend-docscommunity

json/value.bend source

json/value.bend on the hub · documented module

# json/value: a JSON value. Arrays and objects hold their cells inside the# type (JCons, JPair, JNil) rather than in a List, so every traversal is a# structural recursion on one argument -- which Bend's termination checker# accepts, and which keeps laws provable. Build and read them through the# defs below, never by hand.import Baseimport ../lazy/lazy.bend as Lazy# a JSON value; JNil, JCons and JPair are the cells of arrays and objectstype Json is Data:  JNull{}  JBool{b: Bool}  JNum{raw: String}  JStr{s: String}  JArr{items: Json}  JObj{pairs: Json}  JNil{}  JCons{head: Json, tail: Json}  JPair{key: String, val: Json, rest: Json}# reverses a chain of JCons or JPair cells onto accdef reverse(cells: Json, acc: Json) -> Json:  match cells:    case JCons{h, t}:      reverse(t, JCons{h, acc})    case JPair{k, v, r}:      reverse(r, JPair{k, v, acc})    case _:      acc# buildersdef arr.go(items: List<&2, Json>) -> Json:  match items:    case Nil{}:      JNil{}    case Con{h, t}:      JCons{h, arr.go(t)}# an array from a listdef arr(items: List<&2, Json>) -> Json:  JArr{arr.go(items)}def obj.go(pairs: List<&1, String & Json>) -> Json:  match pairs:    case Nil{}:      JNil{}    case Con{(k, v), t}:      JPair{k, v, obj.go(t)}# an object from pairsdef obj(pairs: List<&1, String & Json>) -> Json:  JObj{obj.go(pairs)}# a numberdef num(n: U32) -> Json:  JNum{U32.show(n)}# accessors: a missing key or a wrong kind reads as JNull / None / the default,# so paths chain: get(get(msg, "params"), "textDocument")def find(cells: Json, +key: String) -> Json:  match cells:    case JPair{+k, v, r}:      Lazy.stop(Json, String.eq(k, key), v, _u => find(r, key))    case other:      JNull{}# an object's value at a key; JNull when it is not an object or has no such# keydef get(j: Json, key: String) -> Json:  match j:    case JObj{pairs}:      find(pairs, key)    case other:      JNull{}# a string's text, else the defaultdef str_or(j: Json, default: String) -> String:  match j:    case JStr{s}:      s    case other:      default# a number as a U32, else the defaultdef u32_or(j: Json, default: U32) -> U32:  match j:    case JNum{raw}:      Maybe.default(&2, U32, U32.read(raw), default)    case other:      default# an array's first itemdef first(j: Json) -> Json:  match j:    case JArr{JCons{h, t}}:      h    case other:      JNull{}