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.0"
Quick Start
use ;
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.