json-steroids ð
A high-performance, zero-copy JSON parsing and serialization library for Rust with derive macros for automatic implementation.
Features
- Zero-copy parsing - Strings without escape sequences are borrowed directly from input, avoiding unnecessary allocations
- Fast serialization - Pre-allocated buffers with efficient string escaping and number formatting
- Derive macros - Automatically generate serializers and deserializers for your types
- Minimal dependencies - Only uses
itoaandryufor fast number formatting - Full JSON support - Handles all JSON types including Unicode escape sequences and surrogate pairs
- Pretty printing - Optional indented output for human-readable JSON
- Dynamic values - Parse JSON into a flexible
JsonValuetype when structure is unknown
Installation
Add to your Cargo.toml:
[]
= "0.1.2"
Quick Start
use ;
Performance Benchmarks
Comprehensive benchmark comparison between json-steroids and serde_json. All benchmarks measured with Criterion on Apple M4 Max.
| Category | Benchmark | Description | json-steroids | serde_json | Result |
|---|---|---|---|---|---|
| ð Zero-Copy | borrowed_str_struct_deserialize |
Struct with 3 &str fields (zero-copy) | 35.9 ns | 59.4 ns | â 1.7x faster |
| ð Zero-Copy | cow_struct_deserialize |
Struct with 4 Cow fields (zero-copy) | 67.1 ns | 126.6 ns | â 1.9x faster |
| ð Zero-Copy | zero_copy_vec_strings |
Vec of 4 Cow strings (zero-copy) | 102.9 ns | 274.6 ns | â 2.7x faster |
| ð Zero-Copy | cow_struct_serialize |
Serialize struct with Cow fields | 52.0 ns | 95.9 ns | â 1.8x faster |
| ðĪ Serialization | serialize_simple |
Simple struct (3 fields: String, i64, bool) | 21.9 ns | 36.3 ns | â 1.7x faster |
| ðĪ Serialization | serialize_complex |
Complex nested struct with arrays | 94.3 ns | 162.3 ns | â 1.7x faster |
| ðĪ Serialization | many_fields_serialize |
Struct with 15 mixed-type fields | 107.9 ns | 203.0 ns | â 1.9x faster |
| ðĪ Serialization | large_array_serialize |
Array of 1000 integers | 2.78 Ξs | 2.92 Ξs | â 1.05x faster |
| ðĨ Deserialization | deserialize_simple |
Simple struct (3 fields: String, i64, bool) | 41.7 ns | 50.4 ns | â 1.2x faster |
| ðĨ Deserialization | deserialize_complex |
Complex nested struct with arrays | 273.3 ns | 365.5 ns | â 1.3x faster |
| ðĨ Deserialization | many_fields_deserialize |
Struct with 15 mixed-type fields | 261.5 ns | 352.4 ns | â 1.3x faster |
| ðĨ Deserialization | large_array_deserialize |
Array of 1000 integers | 3.88 Ξs | 6.48 Ξs | â 1.7x faster |
| ð Round-Trip | roundtrip_complex |
Serialize + deserialize complex struct | 395.2 ns | 533.8 ns | â 1.4x faster |
| ðŊ Dynamic | parse_dynamic |
Parse to JsonValue (structure unknown) | 211.7 ns | 330.5 ns | â 1.6x faster |
| ðŊ Dynamic | deeply_nested_parse |
Parse deeply nested JSON (64+ levels) | 426.5 ns | 666.2 ns | â 1.6x faster |
| ðĪ Serialization | string_serialize_with_escapes |
String with escape sequences (\n, \t, etc.) | 46.4 ns | 43.4 ns | â ïļ 0.94x |
| ðĪ Serialization | string_serialize_no_escapes |
Plain string without escapes | 30.3 ns | 28.8 ns | â ïļ 0.95x |
Performance Summary
- â json-steroids wins: 14 of 17 benchmarks (82%)
- ð 1.7-2.7x faster for zero-copy operations with
Cow<'de, str>and&'de str - ⥠21-88% faster for typical serialize/deserialize workloads
- ð 67% faster for large array deserialization
- ðŊ Best use cases: Zero-copy strings, structs, arrays, complex structures, dynamic parsing
- â ïļ serde_json wins: String escaping (6%), simple strings (5%)
Why Choose json-steroids?
Optimized for real-world use cases:
- ð Zero-copy string parsing - Strings without escape sequences are borrowed directly (
Cow::Borrowed) - ðĶ Complex nested structures - 20-35% faster serialization and deserialization
- ð Dynamic JSON parsing - 60% faster when structure is unknown
- ðŊ Type-safe numbers - Specific methods for each integer/float type (no implicit conversions)
- ðū Memory efficient - Pre-allocated buffers, minimal reallocations
- ð ïļ Production ready - Handles Unicode escapes, surrogate pairs, all JSON edge cases
Note: Run
cargo benchto measure performance on your hardware. Results may vary based on CPU architecture and workload patterns.
Key Performance Features
- Zero-copy string parsing - Strings without escape sequences are borrowed directly, avoiding allocations
- Cow<'de, str> support - True zero-copy deserialization with
Cow::Borrowedfor strings without escapes - Fast number formatting - Uses
itoaandryufor optimized integer and float serialization - Efficient memory management - Pre-allocated buffers minimize reallocations
- Optimized string escaping - Fast-path detection for strings that don't need escaping
- Minimal overhead - Streamlined trait implementations with no unnecessary abstractions
Zero-Copy Deserialization
json-steroids supports true zero-copy deserialization using Cow<'de, str>:
use from_str;
use Cow;
// Zero-copy: strings without escape sequences
let json = r#""hello world""#;
let result: = from_str.unwrap;
assert!; // No allocation!
// In collections - zero-copy for all elements without escapes
let json = r#"["apple","banana","cherry"]"#;
let result: = from_str.unwrap;
// All three elements are Cow::Borrowed - zero allocations!
// Automatic handling of escapes
let json = r#""hello\nworld""#;
let result: = from_str.unwrap;
assert!; // Owned only when necessary
Performance advantage: json-steroids with Cow<'de, str> is ~30% faster than serde_json's zero-copy mode and ~2x faster for serialization!
Running Benchmarks
To run benchmarks on your own system:
View the detailed HTML report:
Derive Macros
#[derive(Json)]
The combined derive macro that implements both JsonSerialize and JsonDeserialize:
use Json;
#[derive(JsonSerialize)] and #[derive(JsonDeserialize)]
Use these when you only need one direction:
use ;
Field Renaming
Use the #[json(rename = "...")] attribute to customize field names in JSON:
use Json;
Enum Support
Enums are fully supported with different representations:
use Json;
// Unit variants serialize as strings
// Tuple and struct variants use object notation
API Reference
Serialization Functions
// Compact JSON output
;
// Pretty-printed JSON with 2-space indentation
;
Deserialization Functions
// Parse from string slice
;
// Parse from bytes
;
Dynamic Parsing
When the JSON structure isn't known at compile time:
use ;
let json = r#"{"name": "test", "values": [1, 2, 3]}"#;
let value = parse.unwrap;
// Access fields using indexing
assert_eq!;
assert!;
assert_eq!;
// Check types
assert!;
assert!; // Missing fields return null
JsonValue Type
The JsonValue enum represents any JSON value:
Methods available on JsonValue:
- Type checking:
is_null(),is_bool(),is_number(),is_string(),is_array(),is_object() - Value extraction:
as_bool(),as_i64(),as_u64(),as_f64(),as_str(),as_array(),as_object() - Ownership:
into_string(),into_array(),into_object() - Indexing:
value["key"]for objects,value[0]for arrays
Supported Types
Primitives
- Booleans:
bool - Integers:
i8,i16,i32,i64,isize,u8,u16,u32,u64,usize - Floats:
f32,f64
Strings
String&str(serialize only)Cow<str>
Collections
Vec<T>[T; N](arrays, serialize only)HashMap<K, V>(K must be string-like)BTreeMap<K, V>(K must be string-like)
Wrapper Types
Option<T>- Serializes asnullwhenNoneBox<T>
Tuples
Tuples up to 8 elements are supported and serialize as JSON arrays:
let tuple = ;
let json = to_string; // [1,"hello",true]
Error Handling
The library provides detailed error messages:
use ;
let result: = from_str;
match result
Error types include:
UnexpectedEnd- Input ended unexpectedlyUnexpectedChar(char, usize)- Unexpected character at positionExpectedChar(char, usize)- Expected specific characterExpectedToken(&str, usize)- Expected token (e.g., "string", "number")InvalidNumber(usize)- Invalid number formatInvalidEscape(usize)- Invalid escape sequenceInvalidUnicode(usize)- Invalid Unicode escapeInvalidUtf8- Invalid UTF-8 encodingMissingField(String)- Required field missing during deserializationUnknownVariant(String)- Unknown enum variantTypeMismatch- Type mismatch during deserializationNestingTooDeep(usize)- JSON nesting exceeds maximum depth (128)
Performance
json-steroids is designed for high performance:
Zero-Copy Parsing
Strings that don't contain escape sequences are borrowed directly from the input buffer using Cow<str>, avoiding allocation:
// This string has no escapes - zero allocation!
let json = r#"{"name": "hello world"}"#;
// This string has escapes - allocation needed to unescape
let json = r#"{"name": "hello\nworld"}"#;
Fast Number Formatting
Uses the itoa and ryu crates for extremely fast integer and floating-point formatting.
Efficient String Escaping
The serializer uses a fast path that checks if escaping is needed before processing:
// Fast path - no escaping needed
let s = "hello world";
// Slow path - escaping required
let s = "hello\nworld";
Pre-allocated Buffers
The JsonWriter pre-allocates buffer space to minimize reallocations during serialization.
Architecture
json-steroids/
âââ src/
â âââ lib.rs # Public API and re-exports
â âââ parser.rs # Zero-copy JSON parser
â âââ writer.rs # Fast JSON serializer
â âââ value.rs # Dynamic JsonValue type
â âââ traits.rs # JsonSerialize/JsonDeserialize traits + impls
â âââ error.rs # Error types
âââ json-steroids-derive/
âââ src/
âââ lib.rs # Procedural macros
Examples
Nested Structures
use Json;
let company = Company ;
let json = to_string;
Working with Optional Fields
use ;
// Missing optional fields default to None
let json = r#"{"username": "alice"}"#;
let profile: UserProfile = from_str.unwrap;
assert!;
assert!;
// Explicit null also becomes None
let json = r#"{"username": "bob", "bio": null, "age": 25}"#;
let profile: UserProfile = from_str.unwrap;
assert!;
assert_eq!;
Pretty Printing
use ;
let config = Config ;
let json = to_string_pretty;
// Output:
// {
// "debug": true,
// "port": 8080
// }
Custom Serialization with JsonWriter
For advanced use cases, you can use JsonWriter directly:
use JsonWriter;
let mut writer = new;
writer.begin_object;
writer.write_key;
writer.write_string;
writer.write_comma;
writer.write_key;
writer.begin_array;
writer.write_i64;
writer.write_comma;
writer.write_i64;
writer.end_array;
writer.end_object;
let json = writer.into_string;
// {"name":"custom","values":[1,2]}
Running Benchmarks
Running Tests
License
This project is licensed under the MIT License - see the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.