1 # ezjson: JSON for Bend 2, with a parser, a printer and a pull cursor 2 # 3 # `parse` reads text into Maybe Json. `print` writes compact text and 4 # `pretty` indented text. `cursor` reads one event at a time. Build null, 5 # booleans, numbers, strings, arrays, and objects; read them with get, at, and 6 # as_bool, as_str, as_num, as_u32, as_f32; has and len tell a missing key or 7 # index from a null; items lists an array's elements, and is_arr and is_obj 8 # tell the containers apart. 9 import Base 10 import ./src/value.bend as Value 11 import ./src/parse.bend as Parse 12 import ./src/print.bend as Print 13 import ./src/pull.bend as Pull 14 15 # a text as a value, or None when it is not JSON 16 def parse(txt: String) -> Maybe<&2, Value.Json>: 17 Parse.parse(txt) 18 19 # a value as compact JSON 20 def print(val: Value.Json) -> String: 21 Print.print(val) 22 23 # a value as JSON indented two spaces a level, one element or member a line, 24 # with no newline at the end 25 def pretty(val: Value.Json) -> String: 26 Print.pretty(val) 27 28 # null 29 def null() -> Value.Json: 30 Value.null() 31 32 # a boolean 33 def bool(flag: Bool) -> Value.Json: 34 Value.bool(flag) 35 36 # a string 37 def str(txt: String) -> Value.Json: 38 Value.str(txt) 39 40 # a JSON number from its text, or null when that text is not one 41 def num(raw: String) -> Value.Json: 42 Value.num(raw) 43 44 # an object from pairs 45 def obj(pairs: List<&1, String & Value.Json>) -> Value.Json: 46 Value.obj(pairs) 47 48 # an array from a list 49 def arr(items: List<&2, Value.Json>) -> Value.Json: 50 Value.arr(items) 51 52 # an object's value at a key; JNull when it is not an object or has no such 53 # key 54 def get(val: Value.Json, key: String) -> Value.Json: 55 Value.get(val, key) 56 57 # an array's item at an index; JNull when it is not an array or has none 58 def at(val: Value.Json, idx: U32) -> Value.Json: 59 Value.at(val, idx) 60 61 # whether an object has a key; false when the value is not an object. Tells 62 # a missing key from a key whose value is null, which `get` does not 63 def has(val: Value.Json, key: String) -> Bool: 64 Value.has(val, key) 65 66 # how many elements an array, or members an object, has; 0 for anything else 67 def len(val: Value.Json) -> U32: 68 Value.len(val) 69 70 # an array's elements, in order; [] when the value is not an array. One 71 # walk of the array, where a loop over `at` walks it again for every index 72 def items(val: Value.Json) -> List<&2, Value.Json>: 73 Value.items(val) 74 75 # whether a value is an array 76 def is_arr(val: Value.Json) -> Bool: 77 Value.is_arr(val) 78 79 # whether a value is an object 80 def is_obj(val: Value.Json) -> Bool: 81 Value.is_obj(val) 82 83 # a boolean, or none when the value is not one 84 def as_bool(val: Value.Json) -> Maybe<&2, Bool>: 85 Value.as_bool(val) 86 87 # a string, or none when the value is not one 88 def as_str(val: Value.Json) -> Maybe<&2, String>: 89 Value.as_str(val) 90 91 # a number's text, or none when the value is not a number 92 def as_num(val: Value.Json) -> Maybe<&2, String>: 93 Value.as_num(val) 94 95 # a number as a U32, or none when it is not one or does not fit 96 def as_u32(val: Value.Json) -> Maybe<&2, U32>: 97 Value.as_u32(val) 98 99 # a number as an F32, or none when it is not one or does not fit 100 def as_f32(val: Value.Json) -> Maybe<&2, F32>: 101 Value.as_f32(val) 102 103 # a cursor at the start of a JSON text. It holds the unread suffix of that 104 # text. A span event keeps its own suffix, so it stays valid after `next` 105 # moves the cursor, and it is gone when the event is dropped 106 def cursor(src: String) -> Pull.Cur: 107 Pull.cursor(src) 108 109 # the next event. Commas and colons are not events. After the root value, 110 # the next call is the end, or an error if another value follows 111 def next(cur: Pull.Cur) -> (Pull.Ev & Pull.Cur): 112 Pull.next(cur) 113 114 # drop the next value, scalar or container, without building it 115 def skip(cur: Pull.Cur) -> Pull.Cur: 116 Pull.skip(cur) 117 118 # the text of a string, key, or number event, copying a span. None otherwise 119 def text(ev: Pull.Ev) -> Maybe<&2, String>: 120 Pull.text(ev)