Standard Library: JSON
Shape provides a typed JSON module for parsing, navigation, serialization, and
direct deserialization into user-defined types with @alias support.
Importing
Section titled “Importing”from std::core::json use { parse, stringify, is_valid }All JSON functions live under the json namespace.
Parsing
Section titled “Parsing”Untyped Parsing
Section titled “Untyped Parsing”json::parse returns a Result<Json, string> — a typed enum that preserves the
structure of the original JSON:
let data = json::parse("{\"name\": \"Alice\", \"age\": 30}")?The return value is a Json enum (see below), not a raw hashmap. This means
every JSON value flowing through your program is fully typed.
Typed Deserialization
Section titled “Typed Deserialization”When you pass a type as the second argument, json::parse deserializes
directly into that struct:
type Trade { symbol: string, price: number, volume: int,}
let t = json::parse("{\"symbol\": \"ES\", \"price\": 4525.50, \"volume\": 1200}", Trade)?print(t.symbol) // "ES"print(t.price) // 4525.5Fields are matched by name. Nested structs are recursively deserialized if their schemas are registered.
Field Aliasing with @alias
Section titled “Field Aliasing with @alias”When JSON keys don’t match Shape field names, use @alias to map between
the wire name and the Shape field:
type Trade { @alias("Close Price") close: number,
@alias("vol.") volume: number,}
let t = json::parse("{\"Close Price\": 100.5, \"vol.\": 1000}", Trade)?print(t.close) // 100.5print(t.volume) // 1000This is especially useful for external data sources with spaces, dots, or
other characters that aren’t valid Shape identifiers. @alias works
consistently across JSON deserialization, Arrow/DataTable column binding,
and Python interop.
The Json Enum
Section titled “The Json Enum”json::parse returns a Json enum with seven variants matching the JSON
specification:
pub enum Json { Null, Bool(bool), Int(int), Number(number), Str(string), Array(any), Object(any),}Pattern Matching
Section titled “Pattern Matching”Use standard pattern matching to inspect JSON values:
let data = json::parse("{\"name\": \"Alice\"}")?
match data { Json::Object(obj) => print("got an object"), Json::Array(arr) => print("got an array"), Json::Str(s) => print(f"got string: {s}"), Json::Int(i) => print(f"got int: {i}"), Json::Number(n) => print(f"got number: {n}"), Json::Bool(b) => print(f"got bool: {b}"), Json::Null => print("got null"),}Navigation Methods
Section titled “Navigation Methods”The Json type has navigation methods for exploring nested structures without
matching at every level:
| Method | Signature | Description |
|---|---|---|
get | get(key: string) -> Json | Look up a key in an object. Returns Json::Null for non-objects or missing keys. |
at | at(index: number) -> Json | Access an array element by index. Returns Json::Null for non-arrays or out-of-range. |
is_null | is_null() -> bool | Check if the value is Json::Null. |
keys | keys() -> Array<string> | Return the keys of an object, or an empty array. |
len | len() -> number | Length of an array or object, or 0. |
Example — navigating nested JSON:
let data = json::parse("{\"users\": [{\"name\": \"Alice\"}, {\"name\": \"Bob\"}]}")?
let first_name = data.get("users").at(0).get("name")// first_name is Json::Str("Alice")
let count = data.get("users").len()// count is 2Navigation never throws. Missing paths return Json::Null, which propagates
through further navigation calls:
let data = json::parse("{\"a\": 1}")?
let missing = data.get("b").get("c").get("d")// missing is Json::Null
assert(missing.is_null())Extracting Primitive Values with as?
Section titled “Extracting Primitive Values with as?”The Json type implements TryFrom<Json> for string, int, number, and
bool. These auto-derive TryInto so the as? operator works directly:
let data = json::parse("{\"name\": \"Alice\", \"score\": 95, \"active\": true}")?
let name = (data.get("name") as? string)?// name is "Alice"
let score = (data.get("score") as? number)?// score is 95.0
let active = (data.get("active") as? bool)?// active is trueIf the JSON value doesn’t match the target type, as? returns an Err:
let data = json::parse("{\"name\": \"Alice\"}")?
let result = data.get("name") as? number// result is Err("Json value is not a number")Serialization
Section titled “Serialization”json::stringify
Section titled “json::stringify”Convert any Shape value to a JSON string. The pretty flag is required and
controls indentation:
let text = json::stringify(value, false)? // compactlet pretty = json::stringify(value, true)? // pretty-printedjson::is_valid
Section titled “json::is_valid”Check whether a string is syntactically valid JSON without parsing it:
let ok = json::is_valid("{\"a\": 1}") // truelet bad = json::is_valid("{invalid}") // falseEnd-to-End Example
Section titled “End-to-End Example”Loading external data with field aliasing and typed extraction:
from std::core::json use { parse, stringify }from std::core::io use { open, read_to_string }
type StockQuote { @alias("Global Quote") quote: QuoteData,}
type QuoteData { @alias("01. symbol") symbol: string,
@alias("05. price") price: number,
@alias("06. volume") volume: number,}
let text = io::read_to_string(io::open("quote.json"))let quote = json::parse(text, StockQuote)?print(f"{quote.quote.symbol}: ${quote.quote.price}")Navigating unknown JSON and converting values on the fly:
from std::core::json use { parse }
let data = json::parse("{\"results\": [{\"name\": \"Alice\", \"score\": 95}]}")?
for i in 0..data.get("results").len() { let entry = data.get("results").at(i) let name = (entry.get("name") as? string)? let score = (entry.get("score") as? number)? print(f"{name}: {score}")}Function Reference
Section titled “Function Reference”| Function | Signature | Description |
|---|---|---|
json::parse(text) | (string) -> Result<Json, string> | Parse JSON into a Json enum |
json::parse(text, Type) | (string, Type) -> Result<Type, string> | Deserialize JSON into a typed struct |
json::stringify(value, pretty) | (any, bool) -> Result<string, string> | Serialize a value to JSON; pretty: true indents output |
json::is_valid(text) | (string) -> bool | Check if a string is valid JSON |
See Also
Section titled “See Also”- Error Handling —
Result,?operator, andas?conversions - Traits —
From/TryFromtraits and auto-derived conversions - Annotations —
@aliasand other field annotations - Python Extension —
@aliasfor Python dict interop