| Crates.io | ron2-derive |
| lib.rs | ron2-derive |
| version | 0.3.0 |
| created_at | 2026-01-20 14:35:49.181789+00 |
| updated_at | 2026-01-25 10:40:44.820759+00 |
| description | Derive macros for RON serialization, deserialization, and schema generation |
| homepage | |
| repository | https://github.com/ron-rs/ron2 |
| max_upload_size | |
| id | 2056701 |
| size | 245,201 |
Derive macros for RON serialization, deserialization, and schema generation.
Note: These macros are re-exported from
ron2with the defaultderivefeature. You only need this crate directly if you want to use the macros without the rest ofron2.
Add to your Cargo.toml:
[dependencies]
ron2 = "0.1" # Includes derive macros by default
Or for standalone use:
[dependencies]
ron2-derive = "0.1"
ron2 = { version = "0.1", default-features = false }
#[derive(Ron)] - Implements ToRon, FromRon, and RonSchema (all three)#[derive(ToRon)] - Serialize to RON#[derive(FromRon)] - Deserialize from RON#[derive(RonSchema)] - Generate RON schema filesuse ron2_derive::Ron;
use ron2::{FromRon, ToRon};
#[derive(Debug, PartialEq, Ron)]
struct Config {
name: String,
port: u16,
#[ron(default)]
debug: bool,
}
fn main() {
// Deserialize
let config: Config = Config::from_ron(r#"(name: "app", port: 8080)"#).unwrap();
// Serialize
let ron = config.to_ron().unwrap();
}
| Attribute | Description |
|---|---|
rename = "Name" |
Use different name in RON |
rename_all = "..." |
Apply rename rule to all fields |
deny_unknown_fields |
Error on unknown fields |
transparent |
Serialize as the single inner field |
Rename rules: camelCase, snake_case, PascalCase, SCREAMING_SNAKE_CASE, lowercase, UPPERCASE
| Attribute | Description |
|---|---|
rename = "name" |
Use different name in RON |
skip |
Skip field entirely |
skip_serializing |
Skip during serialization |
skip_deserializing |
Skip during deserialization |
default |
Use Default::default() if missing |
default = "path" |
Use custom function if missing |
flatten |
Flatten nested struct into parent |
skip_serializing_if = "fn" |
Skip if predicate returns true |
explicit |
Require explicit Some(...) or None |
opt |
Default if missing, skip if equals default |
| Attribute | Description |
|---|---|
rename = "Name" |
Use different name in RON |
skip |
Skip this variant |
Option<T> fields accept bare values:
#[derive(FromRon)]
struct Config {
name: Option<String>,
}
(name: "Alice") // becomes Some("Alice")
(name: Some("Alice")) // also works
(name: None) // None
Use #[ron(explicit)] to require Some(...) or None:
#[derive(FromRon)]
struct Config {
#[ron(explicit)]
value: Option<Option<bool>>,
}
(value: Some(Some(true))) // ok
(value: Some(None)) // ok
(value: None) // ok
(value: true) // ERROR - bare value not allowed
Flattened Option<T> fields are presence-based: if none of T's fields are
present in the parent struct, the value is None. If any inner field is
present, the value is Some(T) (and missing inner fields use defaults).
This means None and Some(T::default()) are indistinguishable in input
when T has defaults. Use a non-flattened Option<T> or an explicit marker
field if you need to preserve that distinction.
#[derive(Ron)]
struct Inner {
#[ron(default)]
x: i32,
#[ron(default)]
y: i32,
}
#[derive(Ron)]
struct Outer {
name: String,
#[ron(flatten)]
inner: Option<Inner>,
}
(name: "none") // inner = None
(name: "some", x: 1) // inner = Some(Inner { x: 1, y: 0 })
Use #[ron(transparent)] to serialize as the inner type:
#[derive(FromRon, ToRon)]
#[ron(transparent)]
struct UserId(u64);
#[derive(FromRon, ToRon)]
struct User {
id: UserId,
name: String,
}
(id: 42, name: "Alice") // UserId is just a number
#[ron(opt)])Use #[ron(opt)] for fields that have sensible defaults and should be omitted from output when equal to that default. This combines default with skip-if-default serialization:
#[derive(Ron, Default, PartialEq)]
struct Config {
name: String,
#[ron(opt)]
count: i32, // Omitted when 0
#[ron(opt)]
enabled: bool, // Omitted when false
}
// Input with defaults omitted:
(name: "app")
// Output when count=0, enabled=false:
Config(name: "app")
// Output when count=5, enabled=true:
Config(name: "app", count: 5, enabled: true)
Requires the field type to implement Default + PartialEq.
MIT OR Apache-2.0