jsonforge
A Rust procedural macro that automatically generates typed Rust data structures from local JSON files.
Features
- Zero-boilerplate type generation — point the macro at a JSON file and get a fully-typed struct instantly.
- Schema inference — field types, optional fields (
null-able), arrays, and nested objects are inferred automatically.
- Runtime mode (default) — structs use owned types (
String, Vec<T>); the raw JSON is embedded as a &str constant via include_str!.
- Embedded mode (opt-in) — structs use
&'static str / &'static [T] fields; data is baked into the binary as a perfect-hash-function (phf) map or a fixed-length static array — no runtime file I/O, no heap allocation.
- Fine-grained visibility — control the visibility of the generated struct type and its data item independently.
- Per-call embedded override — opt individual
json_forge! calls in or out of embedded mode regardless of the Cargo feature flag.
Installation
Add to your Cargo.toml:
[dependencies]
jsonforge = "0.1"
For embedded mode, enable the feature and add the phf runtime crate:
[dependencies]
jsonforge = { version = "0.1", features = ["embedded"] }
phf = "0.13"
Usage
Basic (runtime mode)
use jsonforge::json_forge;
json_forge! {
path = "data/content_types.json",
name = "ContentTypeEntry",
}
fn main() {
let parsed: serde_json::Value = serde_json::from_str(CONTENT_TYPE_ENTRY_JSON).unwrap();
println!("{}", parsed["3gp"]["mime_type"]);
}
Embedded mode
use jsonforge::json_forge;
json_forge! {
path = "data/content_types.json",
name = "ContentTypeEntry",
}
fn main() {
let entry = CONTENT_TYPE_ENTRY.get("3gp").unwrap();
println!("{}", entry.mime_type.unwrap_or("unknown"));
}
All parameters
json_forge! {
path = "data/content_types.json", name = "ContentTypeEntry", vis = pub(crate), data_vis = pub, embedded = false, }
Visibility tokens
| Token |
Meaning |
pub |
Fully public |
pub(crate) |
Visible within the current crate |
pub(super) |
Visible to the parent module |
pub(self) |
Private to the current module (same as private) |
private |
No visibility modifier |
embedded override
| Value |
Behaviour |
| omitted |
Follows the embedded Cargo feature flag |
false |
Forces runtime mode even when the feature is enabled |
true |
Forces embedded mode; requires the embedded feature |
#[json_forge_typed] — Validate and embed a hand-written struct
When you want full control over the struct definition (field names, types, derives,
doc-comments, etc.) but still want compile-time JSON validation and automatic data
embedding, use the #[json_forge_typed] attribute macro.
How it works
- You write the struct with the exact field types you need.
- The macro reads the JSON file at compile time and verifies that every value in it
is compatible with the declared field types, reporting precise errors if not.
- A companion data item is emitted right after the struct definition.
Usage
use jsonforge::json_forge_typed;
#[json_forge_typed(path = "data/content_types.json")]
#[derive(Clone, Copy)]
pub struct ContentTypeEntry {
pub mime_type: Option<&'static str>,
pub group: Option<&'static str>,
pub description: Option<&'static str>,
pub extensions: &'static [&'static str],
pub is_text: bool,
}
#[json_forge_typed(path = "data/content_types.json")]
#[derive(Clone)]
pub struct ContentTypeEntry {
pub mime_type: Option<String>,
pub extensions: Vec<String>,
pub is_text: bool,
}
Parameters
| Key |
Description |
path |
JSON file path relative to CARGO_MANIFEST_DIR (required) |
data_vis |
Visibility of the emitted static/const (default: inherits the struct's vis) |
embedded |
true/false override; defaults to the embedded feature flag |
Supported field types
| Rust type |
JSON type |
Mode |
&'static str |
string |
embedded |
String |
string |
runtime |
bool |
boolean |
both |
i8 … i64, u8 … u64, isize, usize |
integer number |
both |
f32, f64 |
number |
both |
&'static [T] |
array |
embedded |
Vec<T> |
array |
runtime |
Option<T> |
null or T |
both |
Fields with an unrecognised type produce a compile error with the field name.
JSON values incompatible with a field's declared type produce a compile error
with the exact entry key and field path.
Generated items
| JSON shape |
Embedded |
Item |
| Object of objects |
yes |
static NAME: ::phf::Map<&str, Struct> |
| Array |
yes |
static NAME_DATA: [Struct; N] |
| Single object |
yes |
static NAME: Struct |
| Any shape |
no |
const NAME_JSON: &'static str (inlined validated JSON) |
Generated items (json_forge!)
Runtime mode
| Item |
Kind |
Name pattern |
| Struct |
struct |
<Name> |
| Raw JSON |
const &str |
<SCREAMING_SNAKE_NAME>_JSON |
Embedded mode
| Top-level JSON shape |
Data item |
Name pattern |
| Object of objects |
static ::phf::Map<&str, Name> |
<SCREAMING_SNAKE_NAME> |
| Array |
static [T; N] |
<SCREAMING_SNAKE_NAME>_DATA |
| Single object |
static Name |
<SCREAMING_SNAKE_NAME> |
Type inference rules
| JSON type |
Rust type (runtime) |
Rust type (embedded) |
string |
String |
&'static str |
number (integer) |
i64 |
i64 |
number (float) |
f64 |
f64 |
boolean |
bool |
bool |
array |
Vec<T> |
&'static [T] |
object |
nested struct |
nested struct |
null / missing |
Option<T> |
Option<T> |
Fields that are null in any entry across the dataset are automatically promoted to Option<T>.
License
Apache-2.0