Skip to content
vic

lovasoa/json_in_type

Fast json encoder in rust, that encodes the structure of JSON values in their types

lovasoa/json_in_type.json
{
"createdAt": "2018-10-07T16:31:40Z",
"defaultBranch": "master",
"description": "Fast json encoder in rust, that encodes the structure of JSON values in their types ",
"fullName": "lovasoa/json_in_type",
"homepage": "https://crates.io/crates/json_in_type",
"language": "Rust",
"name": "json_in_type",
"pushedAt": "2022-08-30T02:11:25Z",
"stargazersCount": 83,
"topics": [
"json",
"performance",
"rust"
],
"updatedAt": "2024-11-28T16:34:06Z",
"url": "https://github.com/lovasoa/json_in_type"
}

Fast json encoder in rust, that does more at compile time, and less at run time. One notable feature is the ability to encode the structure of JSON objects in their type.

This allows for a very compact representation of objects in memory, and up to an order of magnitude better performance than the traditional approach (used by serde’s json! marco, for instance) where JSON objects are stored in maps.

The goal of this library is to be as close as possible to the performance and memory footprint you would get by writing the json by hand in your source code and using string formatting to insert your dynamic values.

fn write_obj_bad(value: f32) -> String {
format!("{{\"value\":{}}}", value)
}
// Safer, but equivalent and not less efficient :
fn write_obj_good(value: f32) -> String {
( json_object! { value } ).to_json_string()
}
use json_in_type::*;
fn main() {
let void = ();
let list = json_list![42u8, true];
let dynamic_key = "hello";
let json_val = json_object!{
void, list,
[dynamic_key] !: "world"
};
/* The type of json_val is:
InlinedJSONObjectEntry<
(),
InlinedJSONObjectEntry<
JSONListElem<u8,
JSONListElem<JSONtrue,
JSONListEnd>>>,
JSONObjectEntry<
&str, &str,
JSONObjectEnd>>>
*/
assert_eq!(
r#"{"void":null,"list":[42,true],"hello":"world"}"#,
json_val.to_json_string()
);
}

The generated types have a very small memory footprint at runtime. You don’t pay for the json structure, only for what you put in it !

In the next example, we store the following json structure on only two bytes:

{
"result_count" : 1,
"errors" : null,
"results" : [
{"answer":42, "ok":true}
]
}
fn test_memory_size() {
let (result_count, answer) = (1u8, 42u8);
let my_val = json_object! {
result_count,
errors: null,
results: json_list![
json_object!{answer, ok: true}
]
};
// my_val weighs only two bytes, because we stored only 2 u8 in it
assert_eq!(2, ::std::mem::size_of_val(&my_val));
}

This library is generally faster than SERDE. Here are detailed comparison results on different json serialization tasks realized on an AMD Ryzen 5 1600X. See detailed benchmark results.

Encoding 8 nested json objects using a rust macro

Section titled “Encoding 8 nested json objects using a rust macro”

We use serde’s json! and json_in_type’s json_object! macro to encode a nested json object.

We encode a JSON structure composed of 8 nested objects, each of which contains a single key, that is known at compile time. The last nested object contains an integer n that is not known at compile time.

{"nested":{"nested":{"nested":{"nested":{"nested":{"nested":{"nested":{"nested":{"value":n}}}}}}}}}

nested json objects comparison

Encoding a very simple json object using a rust macro

Section titled “Encoding a very simple json object using a rust macro”
{
"void": null,
"list": [1, 2, 3, 3],
"hello": "world"
}

simple object

Encoding a very simple json object using #[derive(...)]

Section titled “Encoding a very simple json object using #[derive(...)]”
{
"void": null,
"list": [1, 2, 3, 3],
"hello": "world"
}

created from the following rust struct

#[derive(Serialize, JSONValue)]
struct MyObject {
void: (),
list: Vec<f64>,
hello: String,
}

simple object