# akari_serde
[](https://crates.io/crates/akari_serde)
[](https://docs.rs/akari_serde)
[](LICENSE)
> **Seamless bidirectional conversion between Akari Values and serde-compatible formats**
A lightweight bridge library that enables conversion between [`akari::Value`](https://docs.rs/akari) and serialization formats supported by the [serde](https://serde.rs) ecosystem, starting with JSON.
---
## ✨ Features
- 🔄 **Bidirectional Conversion** - Convert freely between `akari::Value` ↔ `serde_json::Value`
- 🛡️ **Type-Safe** - Leverages Rust's type system with zero runtime overhead
- 🎯 **Orphan Rule Solution** - Uses the `Trans` mediator pattern to bridge foreign types
- 📦 **Zero Dependencies** - Only depends on `akari` and `serde_json`
- 🚀 **Efficient** - Minimal allocations, recursive conversions optimized for performance
---
## 📦 Installation
Add this to your `Cargo.toml`:
```toml
[dependencies]
akari = "0.2.4"
akari_serde = "0.1.0"
```
---
## 🚀 Quick Start
### Convert Akari Value → JSON Value
```rust
use akari::Value;
use akari_serde::Trans;
use serde_json::Value as JsonValue;
// Create an Akari value
let akari_value = Value::Boolean(true);
// Convert to serde_json Value
let json_value: JsonValue = Trans::from(akari_value).into();
assert_eq!(json_value, serde_json::json!(true));
```
### Convert JSON Value → Akari Value
```rust
use akari::Value;
use akari_serde::Trans;
use serde_json::json;
// Create a JSON value
let json_value = json!({
"name": "Alice",
"age": 30,
"active": true
});
// Convert to Akari Value
let akari_value: Value = Trans::from(json_value).into();
// Access as Akari types
match akari_value {
Value::Dict(map) => {
println!("Name: {:?}", map.get("name"));
println!("Age: {:?}", map.get("age"));
}
_ => unreachable!(),
}
```
### Working with Complex Structures
```rust
use akari::Value;
use akari_serde::Trans;
use serde_json::json;
// Complex nested JSON
let json_data = json!({
"users": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
],
"count": 2,
"active": true
});
// Convert to Akari (for processing)
let akari_value: Value = Trans::from(json_data).into();
// Process with Akari...
// (manipulate, query, transform)
// Convert back to JSON (for serialization)
let json_output: serde_json::Value = Trans::from(akari_value).into();
```
---
## 🏗️ Architecture
### The `Trans` Mediator Pattern
Rust's orphan rule prevents directly implementing `From<JsonValue>` for `akari::Value` (or vice versa) since both are foreign types. The `Trans` enum solves this elegantly:
```rust
pub enum Trans {
Akari(Value), // Wraps akari::Value
Serde(JsonValue), // Wraps serde_json::Value
}
```
**Conversion Flow:**
```
akari::Value → Trans::Akari(v) → Trans → serde_json::Value
↑ ↓
└──────── Trans::Serde(v) ─────┘
```
This two-step conversion is zero-cost at runtime thanks to Rust's optimization.
---
## 🔬 Type Mappings
### Akari → JSON
| `Value::None` | `JsonValue::Null` | Direct mapping |
| `Value::Boolean` | `JsonValue::Bool` | Direct mapping |
| `Value::Numerical(f64)` | `JsonValue::Number` | Converted to `i64` (lossy for floats) |
| `Value::Str` | `JsonValue::String`| Direct mapping |
| `Value::List` | `JsonValue::Array` | Recursive conversion |
| `Value::Dict` | `JsonValue::Object`| Recursive conversion |
### JSON → Akari
| `JsonValue::Null` | `Value::None` | Direct mapping |
| `JsonValue::Bool` | `Value::Boolean` | Direct mapping |
| `JsonValue::Number`| `Value::Numerical` | Converted to `f64` (may lose precision) |
| `JsonValue::String`| `Value::Str` | Direct mapping |
| `JsonValue::Array` | `Value::List` | Recursive conversion |
| `JsonValue::Object`| `Value::Dict` | Recursive conversion |
---
## ⚠️ Important Notes
### Numerical Precision
- **Akari → JSON**: Converts `f64` to `i64`, losing fractional parts
```rust
Value::Numerical(3.14) → json!(3) ```
- **JSON → Akari**: Non-finite numbers (`NaN`, `Infinity`) become `0.0`
```rust
json!(NaN) → Value::Numerical(0.0) ```
### Null Handling
- JSON's `null` maps to Akari's `Value::None`
- Both representations are preserved during round-trip conversion
---
## 📚 Examples
Check out the [`examples/`](examples/) directory for more usage patterns:
```bash
cargo run --example json_conversion
```
---
## 🛣️ Roadmap
- [ ] Support for more serde formats:
- [ ] YAML (`serde_yaml`)
- [ ] TOML (`toml`)
- [ ] MessagePack (`rmp-serde`)
- [ ] BSON (`bson`)
- [ ] Improved numerical conversion strategies
- [ ] Optional features for format-specific optimizations
- [ ] Benchmarks and performance tuning
---
## 🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
---
## 📄 License
This project is dual-licensed under:
- MIT License ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
at your option.
---
## 🔗 Related Projects
- [**akari**](https://fds.rs/akari/) - The core Akari value system
- [**serde**](https://serde.rs) - Serialization framework for Rust
- [**serde_json**](https://docs.rs/serde_json) - JSON support for serde
---
<div align="center">
</div>