# Messy Json
**Rust JSON Parser for dynamically structured documents**
- [Messy Json](#messy-json)
- [Introduction](#introduction)
- [Example](#example)
- [Performance](#performance)
- [Dummy object](#dummy-object)
- [Partial object](#partial-object)
- [Simple object](#simple-object)
## Introduction
The rust ecosystem allows for **very** good compile-time implementation of JSON deserializer to rust structure, however,
things get a bit more sparse when it come to run-time deserialization of dynamically structured objects.
This crate approaches this problems in a simple manner, resembling [`serde_json`'s `Value`](https://docs.serde.rs/serde_json/value/enum.Value.html).
## Example
```rust
use messy_json::*;
use serde::de::DeserializeSeed;
let nested_string = MessyJson::from(MessyJsonInner::String(MessyJsonScalar::new(false)));
let schema: MessyJson = MessyJson::from(MessyJsonInner::Obj(MessyJsonObject::from(MessyJsonObjectInner::new(
vec![(arcstr::literal!("hello"), nested_string)]
.into_iter()
.collect(),
false,
))));
let value = r#"
{
"hello": "world"
}
"#;
let mut deserializer = serde_json::Deserializer::from_str(value);
let parsed: MessyJsonValueContainer = schema.builder(MessyJsonSettings::default()).deserialize(&mut deserializer).unwrap();
println!("{:#?}", parsed)
```
## Performance
This crate is more effecient than [`serde_json`'s `Value`](https://docs.serde.rs/serde_json/value/enum.Value.html) when all the fields are required. The performance par with [`serde_json`'s `Value`](https://docs.serde.rs/serde_json/value/enum.Value.html) when some fields are optional.
However this crate is far behind deserializing using the `proc-macro` from serde (which is not dynamically structured at all).
This gap could be filled using a custom arena-based allocator, like [Bumpalo](https://crates.io/crates/bumpalo) when the `Allocator` trait is merged into `stable`.
This crate implements benchmarks.
The following graphs were run on a machine with the following specs:
- CPU : Intel i9-9900K @ 4.7Ghz
- RAM : 32 Gb RAM @ 2133 Mhz
- Kernel : `5.11.16-arch1-1`
- Rust : `rustc 1.51.0 (2fd73fabe 2021-03-23)`
In the following benchmarks, the `messy_json` crate is compared with deserializer from the [`serde_json`'s `Value`](https://docs.serde.rs/serde_json/value/enum.Value.html) and macro-generated deserializer using `serde`'s `derive`.
### Dummy object
The following benchmark consists of deserializing the JSON Document
```json
{
"hello":
{
"hola": "world"
}
}
```
the accepted schema should looks like the following:
```rust
use std::borrow::Cow;
struct DummyObjNested<'a> {
hola: Cow<'a, str>,
}
struct DummyObj<'a> {
hello: DummyObjNested<'a>,
}
```
The results show that `messy_json` is slower than macro-generated deserializer but faster than using
[`serde_json`'s `Value`](https://docs.serde.rs/serde_json/value/enum.Value.html).
### Partial object
The following benchmark consists of deserializing the JSON Document
```json
{
"hello":
{
"hola": "world"
}
}
```
the accepted schema should looks like the following:
```rust
use serde::{Serialize, Deserialize};
use std::borrow::Cow;
#[derive(Serialize, Deserialize)]
struct PartialObjNested<'a> {
hola: Cow<'a, str>,
}
#[derive(Serialize, Deserialize)]
struct PartialObj<'a> {
hello: PartialObjNested<'a>,
coucou: Option>,
coucou1: Option>,
coucou2: Option>,
}
```
The results show that `messy_json` is slower than macro-generated deserializer and on par with [`serde_json`'s `Value`](https://docs.serde.rs/serde_json/value/enum.Value.html). When using optional values, this crate has to check it has met all of the mandatory values for each object, hence the performance regression. In the future, when the `alloc_api` of the Rust language is merged into `stable`, optimizations could be put in place reducing the time necessary to check for missing fields.
### Simple object
The following benchmark consists of deserializing the JSON Document
```json
{
"hello": "world"
}
```
the accepted schema should looks like the following:
```rust
use std::borrow::Cow;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct SimpleObj<'a> {
hello: Cow<'a, str>,
}
```
The results show that `messy_json` is slower than macro-generated deserializer but is still faster than [`serde_json`'s `Value`](https://docs.serde.rs/serde_json/value/enum.Value.html).