JSON Parsing
Recipe | Crates | Categories |
---|---|---|
json5 | ||
serde_json | ||
simd-json |
[json.incl: fix (P2)](https://github.com/john-cd/rust_howto/issues/439)
serde_json
⮳ is the most commonly used crate for JSON Parsing. simd_json
⮳ is optimized for performance.
Parse JSON with serde_json
serde_json
⮳ offers a JSON serialization file format.
use serde::Deserialize; use serde::Serialize; use serde_json::Result; use serde_json::Value; #[derive(Deserialize, Serialize, Debug)] struct User { name: String, age: u8, phones: Vec<String>, } // Deserialize a JSON string fn main() -> Result<()> { let json_str = r#" { "name": "John Doe", "age": 42, "phones": [ "+1 123456789", "+1 234567890" ] } "#; // Use the `Value` enum to represent any valid JSON value. let parsed: Value = serde_json::from_str(json_str)?; // There is also `from_slice` for parsing from a byte slice `&[u8]`` // and `from_reader` for parsing from any `io::Read` like a `File` or a TCP // stream. // Then access parts of the data by indexing with square brackets. // The result of square bracket indexing is a borrow, so the type is // `&Value`. let name = parsed["name"].as_str().unwrap(); let age = parsed["age"].as_i64().unwrap(); let phones = parsed["phones"].as_array().unwrap(); println!("Name: {}", name); println!("Age: {}", age); println!("Phones: {:?}", phones); // Or use a custom `struct` that implements `Deserialize` let user: User = serde_json::from_str(json_str)?; println!("{:?}", user); // Serialize it back to a JSON string. let u = serde_json::to_string(&user)?; println!("{u}"); // There is also `serde_json::to_vec` which serializes to a `Vec<u8>` // and `serde_json::to_writer`, which serializes to any `io::Write`, // such as a `File` or a TCP stream. Ok(()) }
Parse JSON with json5
json5
⮳ is a Rust JSON5 serializer and deserializer which speaks serde
.
use json5; use serde_json::Value; // JSON5 is an extension to the popular JSON file format that aims to be easier // to write and maintain by hand (e.g. for config files). It is not intended to // be used for machine-to-machine communication. https://json5.org fn main() { let json5_str = r#"{ // comments are allowed unquoted: 'and you can use single quotes', trailingComma: ['in arrays', 'like', 'this', ], hexadecimal: 0xDEADbeef, infinity: Infinity, nan: NaN, nested: { pi: 3.141592653, }, 'quoted key': true, // Quoted keys are allowed "backwardsCompatible": "with JSON", }"#; // Parse the JSON5 string into a `serde_json::Value`. match json5::from_str::<Value>(json5_str) { Ok(value) => { println!("Parsed JSON5: {:#?}", value); if let Some(nested) = value.get("nested") { if let Some(pi) = nested.get("pi") { println!("Pi: {}", pi); } } if let Some(hex) = value.get("hexadecimal") { println!("Hex: {}", hex); } if let Some(inf) = value.get("infinity") { println!("Infinity: {}", inf); } if let Some(nan) = value.get("nan") { println!("NaN: {}", nan); } if let Some(unquoted) = value.get("unquoted") { println!("Unquoted: {}", unquoted); } if let Some(quoted_key) = value.get("quoted key") { println!("Quoted Key: {}", quoted_key); } } Err(e) => { eprintln!("Error parsing JSON5: {}", e); } } }
Parse JSON with simd-json
simd-json
⮳ is a high-performance JSON parser based on a port of simdjson
.
use simd_json::OwnedValue; use simd_json::derived::ValueObjectAccess; use simd_json::derived::ValueObjectAccessAsArray; use simd_json::derived::ValueObjectAccessAsScalar; use simd_json::prelude::*; // `simd-json` is a Rust port of the extremely fast simdjson c++ library with // `serde` compatibility. For best performance, use `mimalloc` or `jemalloc` // instead of the system allocator used by default. For example: // use mimalloc::MiMalloc; // // #[global_allocator] // static GLOBAL: MiMalloc = MiMalloc; fn main() { let mut json_string = br#" { "name": "Alice", "age": 30, "city": "New York", "numbers": [1, 2, 3, 4, 5], "nested": { "value": true } } "# .to_vec(); // Parse the JSON string into a BorrowedValue. // BorrowedValue is designed for read-only access and avoids unnecessary // copying, making it very fast. match simd_json::to_borrowed_value(&mut json_string) { Ok(json) => { println!("Parsed JSON: {:?}", json); // Access values using ValueAccess traits if let Some(name) = json.get_str("name") { println!("Name: {}", name); } if let Some(age) = json.get_u64("age") { println!("Age: {}", age); } if let Some(city) = json.get_str("city") { println!("City: {}", city); } if let Some(numbers) = json.get_array("numbers") { println!("Numbers: {:?}", numbers); } if let Some(nested) = json.get("nested") { if let Some(nested_value) = nested.get_bool("value") { println!("Nested Value: {}", nested_value); } } } Err(e) => { eprintln!("Error parsing JSON: {}", e); } } // Example using OwnedValue (for modifications) // This is slower then the BorrowedValue as a tradeoff for getting rid of // lifetimes. let mut owned_json: OwnedValue = simd_json::to_owned_value(&mut json_string).unwrap(); if let Some(name) = owned_json.get_mut("name") { *name = OwnedValue::from("Bob"); } println!("Modified Owned JSON: {}", owned_json.to_string()); }