Rust API¶
The vexy-json crate is a thin facade. It re-exports the parser from
vexy-json-core and, with its default serde feature, the items of
vexy-json-serde. Generated API documentation for each crate is on
docs.rs/vexy-json.
Parsing functions¶
pub fn parse(input: &str) -> vexy_json::Result<Value>;
pub fn parse_with_options(input: &str, options: ParserOptions) -> vexy_json::Result<Value>;
parse uses ParserOptions::default(), which turns on every syntax
extension. parse_with_options takes the options by value. Neither function
repairs input; for that, see parse_with_fallback in
Repairing incomplete input.
use vexy_json::{parse, parse_with_options, ParserOptions};
fn main() -> vexy_json::Result<()> {
let value = parse("{name: 'Vexy', enabled: true,}")?;
println!("{value}"); // {"name": "Vexy", "enabled": true}
let options = ParserOptions { allow_comments: false, ..ParserOptions::default() };
let value = parse_with_options("[1, 2, 3]", options)?;
println!("{value}"); // [1, 2, 3]
Ok(())
}
vexy_json::Result<T> is an alias for std::result::Result<T, vexy_json::Error>.
Value¶
Value is the parsed document:
pub enum Value {
Null,
Bool(bool),
Number(Number),
String(String),
Array(Vec<Value>),
Object(FxHashMap<String, Value>),
}
pub enum Number {
Integer(i64),
Float(f64),
}
Object uses FxHashMap from the rustc-hash crate, so member order is not
kept.
Reading values¶
| Method | Returns |
|---|---|
is_null(), is_bool(), is_number(), is_string(), is_array(), is_object() |
bool |
as_bool() |
Option<bool> |
as_i64() |
Option<i64> |
as_f64() |
Option<f64> |
as_str() |
Option<&str> |
as_array() |
Option<&Vec<Value>> |
as_object() |
Option<&FxHashMap<String, Value>> |
Value implements Index<&str> and Index<usize>. Indexing never panics: a
missing key, an index out of range or indexing the wrong type returns
Value::Null.
use vexy_json::{parse, Value};
let value = parse("{user: {name: 'Ada', roles: [admin, dev]}}").unwrap();
assert_eq!(value["user"]["name"].as_str(), Some("Ada"));
assert_eq!(value["user"]["roles"][1].as_str(), Some("dev"));
assert!(value["user"]["email"].is_null());
if let Value::Object(map) = &value["user"] {
println!("{} members", map.len()); // 2 members
}
Number::as_f64() converts either variant to f64.
Printing values¶
Value implements Display, which writes JSON-like text with a space after
each : and ,. Display does not escape string contents: a string that
contains " or a newline is written as is. For guaranteed valid JSON output,
serialize with Serde (see below) or use the vexy-json CLI, which escapes
strings.
ParserOptions¶
ParserOptions is a plain struct with public fields and a Default
implementation. The fields and their defaults are listed in
Parser options. Use struct update syntax to change only some
fields:
use vexy_json::ParserOptions;
let options = ParserOptions {
max_depth: 512,
..ParserOptions::default()
};
With the core crate's serde feature, ParserOptions also implements
Serialize and Deserialize, and missing fields take their defaults.
Errors¶
vexy_json::Error (also exported as ParseError) is an enum built with
thiserror. Its Display text includes a byte position:
| Variant | Message |
|---|---|
UnexpectedChar(char, usize) |
Unexpected character 'x' at position N |
UnexpectedEof(usize) |
Unexpected end of input at position N |
InvalidNumber(usize) |
Invalid number format at position N |
InvalidEscape(usize) |
Invalid string escape sequence at position N |
InvalidUnicode(usize) |
Invalid Unicode escape at position N |
UnterminatedString(usize) |
Unterminated string starting at position N |
TrailingComma(usize) |
Trailing comma at position N |
Expected { expected, found, position } |
Expected X but found Y at position N |
DepthLimitExceeded(usize) |
Depth limit exceeded at position N |
Custom(String) |
Custom error: … |
RepairFailed(String) |
JSON repair failed: … |
BracketMismatch(usize, char, char) |
Bracket mismatch at position N: expected X, found Y |
UnbalancedBrackets(usize, usize) |
Unbalanced brackets: N extra opening, M extra closing |
MaxRepairsExceeded(usize) |
Maximum repair attempts exceeded (N) |
Positions are zero-based byte offsets into the input string. Span (start
and end byte offsets) is exported for code that works with tokens.
Streaming¶
Newline-delimited JSON¶
NdJsonParser parses one value per line. Feed it text in chunks of any size;
each call to feed returns the values completed so far, and finish returns
the last value if the input did not end with a newline.
use vexy_json::NdJsonParser;
fn main() -> vexy_json::Result<()> {
let mut parser = NdJsonParser::new();
let values = parser.feed("{\"id\": 1}\n{id: 2}\n")?;
assert_eq!(values.len(), 2);
let rest = parser.finish()?;
assert!(rest.is_empty());
Ok(())
}
NdJsonParser::with_options(options) applies custom ParserOptions to each
line. line_number() reports the current line.
Event stream¶
StreamingParser produces StreamingEvent values as input arrives:
StartObject, EndObject, StartArray, EndArray, ObjectKey(String),
Null, Bool(bool), Number(String), String(String) and EndOfInput.
use vexy_json::{StreamingEvent, StreamingParser};
fn main() -> vexy_json::Result<()> {
let mut parser = StreamingParser::new();
parser.feed(r#"{"name": "#)?;
parser.feed(r#""Alice", "age": 30}"#)?;
parser.finish()?;
while let Some(event) = parser.next_event()? {
match event {
StreamingEvent::ObjectKey(key) => println!("key {key}"),
StreamingEvent::EndOfInput => break,
other => println!("{other:?}"),
}
}
Ok(())
}
StreamingValueBuilder turns a sequence of events back into a Value. The
repository's examples/streaming_example.rs shows these types together; run
it with cargo run --example streaming_example.
Serde¶
With the default serde feature, vexy_json re-exports SerdeValue, a
newtype around Value that implements Serialize and Deserialize, with
From conversions in both directions.
Value itself derives Serialize and Deserialize when the core crate's
serde feature is on. The derive keeps the enum structure, so
serde_json::to_string(&value) produces tagged output such as
{"Object":{"a":{"Number":{"Integer":1}}}}, not plain JSON.
Other exports¶
vexy-json-core exports further entry points that the facade crate does not
re-export. Import them from vexy_json_core directly:
- Alternative parsers:
parse_iterative,parse_recursive,parse_optimized,parse_optimized_v2,parse_optimized_v3and their_with_optionsand_with_statsvariants. - Repair:
parse_with_fallback,parse_with_detailed_repair_tracking,JsonRepairer,EnhancedParseResult,ParsingTier,RepairAction. - Large inputs:
parse_parallel,parse_ndjson_parallel,ParallelParser,ParallelConfig,parse_lazyandLazyParser. - Transformation:
normalize,optimize,JsonNormalizer,CanonicalNormalizer,AstOptimizer.
These functions are public but are not covered by this guide; read their doc comments on docs.rs before relying on them.