Asynchronous streaming JSON pull parser built on lexscan
///|
async test "read an array of objects in chunks" {
let parts = ["[{\"name\": \"a\", \"n\": 1}, {\"na", "me\": \"b\", \"n\": 2}]"]
let mut i = 0
let parser = @ajson.Parser::new(
@lexbuf.AsyncLexbuf::from_fn(() => {
if i < parts.length() {
i += 1
Some(parts[i - 1])
} else {
None
}
}),
)
guard parser.next_event() is Some(StartArray) else { fail("not an array") }
let names = []
while parser.next_value() is Some(Object(members)) {
if members.get("name") is Some(String(name)) {
names.push(name)
}
}
debug_inspect(names, content="[\"a\", \"b\"]")
assert_true(parser.next_event() is None)
}let parser = @ajson.Parser::from_reader(@stdio.stdin.text, multiple_values=true)
parser.each_value(value => println(value.stringify()))moon build --target native --release
./_build/native/release/build/cmd/example/example.exe count < big.jsonParser::new(lexbuf : @lexbuf.AsyncLexbuf, max_depth? : Int = 1024,
max_string_length? : Int, multiple_values? : Bool = false) -> Parser
Parser::from_reader[R : @io.TextReader](reader : R, ...same options) -> Parser
async Parser::next_event(self) -> Event? // None at the end of input
async Parser::next_value(self) -> Json? // next complete value
async Parser::next_member(self) -> (String, Json)?
async Parser::skip_value(self) -> Bool
async Parser::each_value(self, f : async (Json) -> Unit) -> Unit
Parser::position(self) -> Position
Parser::depth(self) -> Int
enum Event { StartObject, EndObject, StartArray, EndArray, Key(String), Value(Json) }
struct Position { offset : Int, line : Int, column : Int }
suberror ParseError {
UnexpectedChar(Position, Char), UnexpectedEof(Position),
UnpairedSurrogate(Position), DepthLimitExceeded(Position, Int),
TooLong(Position, Int), Interrupted
}| target | @json.parse | next_value | events only | max_string_length set |
|---|---|---|---|---|
| native, released | 17 | 187 | 172 | 509 |
| native, master | 17 | 119 | 105 | 445 |
| js, released | 27 | 276 | 246 | 535 |
| js, master | 28 | 129 | 106 | 429 |
| wasm, released | 43 | 523 | 500 | 1494 |
| wasm, master | 43 | 325 | 310 | 1337 |
moon run --target native --release cmd/benchmark| target, moonc | StringScanner | Lexbuf (sync) | AsyncLexbuf | ratio |
|---|---|---|---|---|
| native, released | 10 | 18.6 | 141 | 7.6x |
| native, master | 9 | 17.8 | 63 | 3.5x |
| js, released | 22 | 50.8 | 245 | 4.8x |
| js, master | 19 | 49.2 | 83 | 1.7x |
| wasm, released | 20 | 48.6 | 400 | 8.2x |
| wasm, master | 16 | 42.5 | 200 | 4.7x |
moon run --target native --release cmd/asynctaxmoon test --target native
moon test --target js
moon test --target wasmimpl Show for ParseErrorpub struct Parser {
// private fields
}fn[R : TextReader] Parser::from_reader(reader : R, max_depth? : Int, max_string_length? : Int, multiple_values? : Bool) -> Parserfn Parser::new(lexbuf : AsyncLexbuf, max_depth? : Int, max_string_length? : Int, multiple_values? : Bool) -> ParserInstall
Download zipAsynchronous streaming JSON pull parser built on lexscan