json

Zero-copy JSON parser and serialiser. The parser returns slices that point directly into the source buffer – no allocations for strings. The serialiser writes directly to a caller-supplied buffer. Both are thread-safe (no global state).

Types

JsonValue (enum)

A tagged union covering all JSON types:

enum JsonValue {
    Null
    Bool(bool)
    Int(i64)
    Float(f64)
    Str([]i8)             // slice into original source buffer (zero-copy)
    Array([]JsonValue)    // elements stored in caller's region
    Object([]JsonPair)    // key-value pairs
}

JsonPair (struct)

struct JsonPair {
    key: []i8             // slice into source buffer
    val: JsonValue
}

Parser (struct)

struct Parser {
    src: []i8
    pos: i64
}

Usage

Parsing JSON

import json

fn main() {
    let src = "{\"name\": \"Jda\", \"version\": 1, \"fast\": true}"

    let val = json_parse(src).unwrap()

    let name = val.get("name").unwrap().as_str().unwrap()
    let version = val.get("version").unwrap().as_i64().unwrap()
    let fast = val.get("fast").unwrap().as_bool().unwrap()
}

Writing JSON

import json

fn main() {
    let val = JsonValue::Object([
        JsonPair { key: "status", val: JsonValue::Str("ok") },
        JsonPair { key: "code", val: JsonValue::Int(200) },
    ])

    let buf = [4096]i8
    let n = json_write(val, buf)
    // buf now contains: {"status":"ok","code":200}

    // Pretty-printed output
    let n2 = json_write_pretty(val, buf)
}

Function Reference

FunctionSignatureDescription
json_parse(src: []i8) -> Result<JsonValue, []i8>Parse a JSON string into a value
json_write(val: ref JsonValue, buf: []mut i8) -> i64Serialise to compact JSON
json_write_pretty(val: ref JsonValue, buf: []mut i8) -> i64Serialise to indented JSON

Detailed API

json_parse

fn json_parse(src: []i8) -> Result<;JsonValue, []i8>

Parse a complete JSON document from src. Returns Ok(JsonValue) on success or Err(message) on failure. Trailing characters after the root value are an error.

let result = json_parse("{\"x\": 42}")
match result {
    Ok(val) => {
        let x = val.get("x").unwrap().as_i64().unwrap()
        print(x)   // 42
    }
    Err(msg) => {
        // handle parse error
    }
}

Supported JSON types: null, booleans, integers, floating-point numbers, strings (with escape sequences), arrays, and objects.

json_write

fn json_write(val: ref JsonValue, buf: []mut i8) -> i64

Serialise a JsonValue to compact JSON (no whitespace) into the provided buffer.

let val = JsonValue::Array([
    JsonValue::Int(1),
    JsonValue::Int(2),
    JsonValue::Int(3),
])
let buf = [4096]i8
let n = json_write(val, buf)
// buf[0..n] contains: [1,2,3]

Returns: Number of bytes written to buf.

json_write_pretty

fn json_write_pretty(val: ref JsonValue, buf: []mut i8) -> i64

Serialise a JsonValue to indented JSON with 2-space indentation and newlines.

let val = JsonValue::Object([
    JsonPair { key: "name", val: JsonValue::Str("Jda") },
])
let buf = [4096]i8
let n = json_write_pretty(val, buf)
// Output:
// {
//   "name": "Jda"
// }

Returns: Number of bytes written to buf.

JsonValue Methods

The JsonValue enum provides accessor methods for extracting typed values:

as_str

fn as_str(self) -> Result<;[]i8, []i8>

Extract the string slice from a Str variant.

let val = json_parse("\"hello\"").unwrap()
let s = val.as_str().unwrap()   // "hello"

as_i64

fn as_i64(self) -> Result<;i64, []i8>

Extract an integer from Int or truncate from Float.

let val = json_parse("42").unwrap()
let n = val.as_i64().unwrap()   // 42

as_f64

fn as_f64(self) -> Result<;f64, []i8>

Extract a float from Float or convert from Int.

let val = json_parse("3.14").unwrap()
let f = val.as_f64().unwrap()   // 3.14

as_bool

fn as_bool(self) -> Result<;bool, []i8>

Extract a boolean from a Bool variant.

is_null

fn is_null(self) -> bool

Returns true if the value is Null.

get

fn get(self, key: ref []i8) -> Result<;JsonValue, []i8>

Look up a key in an Object. Returns Err("key not found") if the key does not exist or Err("not an object") if the value is not an object.

let obj = json_parse("{\"name\": \"Jda\"}").unwrap()
let name = obj.get("name").unwrap()

index

fn index(self, i: i64) -> Result<;JsonValue, []i8>

Get an element by index from an Array.

let arr = json_parse("[10, 20, 30]").unwrap()
let second = arr.index(1).unwrap().as_i64().unwrap()   // 20

len

fn len(self) -> i64

Get the length of an Array, Object, or Str. Returns 0 for other types.

let arr = json_parse("[1, 2, 3]").unwrap()
print(arr.len())   // 3