Skip to main content

basic/
basic.rs

1//! Parse untrusted JSON strictly, inspect it, and serialize it back.
2//!
3//! ```sh
4//! cargo run -p reliakit-json --example basic
5//! ```
6
7use reliakit_json::{parse_with_limits, to_compact_string, JsonLimits, JsonValue};
8
9fn main() {
10    // Treat this as untrusted input: parse under a conservative limit profile.
11    let input = r#"{ "service": "api", "port": 8080, "tags": ["a", "b"], "enabled": true }"#;
12    let limits = JsonLimits::conservative();
13
14    let value = match parse_with_limits(input.as_bytes(), limits) {
15        Ok(value) => value,
16        Err(err) => {
17            eprintln!("rejected: {err}");
18            return;
19        }
20    };
21
22    if let JsonValue::Object(object) = &value {
23        if let Some(port) = object.get("port").and_then(JsonValue::as_number) {
24            println!("port = {}", port.to_u64().unwrap());
25        }
26        if let Some(tags) = object.get("tags").and_then(JsonValue::as_array) {
27            println!("tags = {}", tags.len());
28        }
29    }
30
31    // Deterministic, member-order-preserving serialization.
32    println!("compact = {}", to_compact_string(&value));
33
34    // Strict by default: these are all rejected.
35    for bad in [r#"{"a":1,"a":2}"#, "{ /* c */ }", "[1,]", "NaN"] {
36        match parse_with_limits(bad.as_bytes(), limits) {
37            Ok(_) => println!("accepted (unexpected): {bad}"),
38            Err(err) => println!("rejected {bad:?}: {}", err.kind_str()),
39        }
40    }
41}
42
43// Small helper so the example prints something readable for each error kind.
44trait KindStr {
45    fn kind_str(&self) -> &'static str;
46}
47
48impl KindStr for reliakit_json::JsonError {
49    fn kind_str(&self) -> &'static str {
50        use reliakit_json::JsonErrorKind::*;
51        match self.kind() {
52            DuplicateKey => "duplicate key",
53            UnexpectedByte => "unexpected byte",
54            InvalidNumber => "invalid number",
55            TrailingData => "trailing data",
56            _ => "other",
57        }
58    }
59}