16 releases (breaking)
Uses new Rust 2024
| new 0.13.0 | May 22, 2026 |
|---|---|
| 0.11.0 | Mar 29, 2026 |
| 0.2.0 | Dec 30, 2025 |
#7 in #json-pointer
432 downloads per month
Used in 2 crates
(via ploidy-pointer)
67KB
1.5K
SLoC
Derive macros for the JsonPointee and JsonPointerTarget traits.
This crate provides two derive macros:
JsonPointeegenerates an implementation of theJsonPointeetrait for traversing structs and enums with JSON Pointer (RFC 6901) syntax. This macro supports Serde-like attributes.JsonPointerTargetgenerates an implementation of theJsonPointerTargettrait for extracting a reference to the concrete target type from a type-erased pointee.
Container attributes
Container-level attributes apply to structs and enums:
#[ploidy(pointer(tag = "field"))]- Use the internally tagged enum representation, with the given field name for the tag. Supported on enums only.#[ploidy(pointer(tag = "t", content = "c"))]- Use the adjacently tagged enum representation, with the given field names for the tag and contents. Supported on enums only.#[ploidy(pointer(untagged))]- Use the untagged enum representation. Supported on enums only.#[ploidy(pointer(rename_all = "case"))]- Rename all struct fields or enum variants according to the given case. The supported cases arelowercase,UPPERCASE,PascalCase,camelCase,snake_case,SCREAMING_SNAKE_CASE,kebab-case, andSCREAMING-KEBAB-CASE.#[ploidy(pointer(crate = "path::to::ploidy_pointer"))]- Override the path to theploidy_pointercrate. Defaults to::ploidy_pointer.
Variant Attributes
Variant-level attributes apply to enum variants:
#[ploidy(pointer(rename = "name"))]- Access this variant using the given name, instead of its Rust name.#[ploidy(pointer(skip))]- Make this variant inaccessible, except for the tag field if using the internally or adjacently tagged enum representation.
Field Attributes
Field-level attributes apply to struct and enum variant fields:
#[ploidy(pointer(rename = "name"))]- Access this variant using the given name, instead of its Rust name.#[ploidy(pointer(flatten))]- Remove one layer of structure between the container and field. Supported on named fields only.#[ploidy(pointer(skip))]- Exclude the field from pointer access.
Examples
Struct flattening
# use ploidy_pointer::{JsonPointerTarget, JsonPointee, JsonPointeeExt};
# fn main() -> Result<(), Box<dyn std::error::Error>> {
#[derive(JsonPointee, JsonPointerTarget)]
struct User {
name: String,
#[ploidy(pointer(flatten))]
contact: ContactInfo,
}
#[derive(JsonPointee, JsonPointerTarget)]
struct ContactInfo {
email: String,
phone: String,
}
let user = User {
name: "Alice".to_owned(),
contact: ContactInfo {
email: "[email protected]".to_owned(),
phone: "555-1234".to_owned(),
},
};
let name: &str = user.pointer("/name")?;
assert_eq!(name, "Alice");
let email: &str = user.pointer("/email")?;
assert_eq!(email, "[email protected]");
let phone: &str = user.pointer("/phone")?;
assert_eq!(phone, "555-1234");
# Ok(())
# }
Renaming fields
# use ploidy_pointer::{JsonPointerTarget, JsonPointee, JsonPointeeExt};
# fn main() -> Result<(), Box<dyn std::error::Error>> {
#[derive(JsonPointee, JsonPointerTarget)]
#[ploidy(pointer(rename_all = "snake_case"))]
enum ApiResponse {
SuccessResponse { data: String },
#[ploidy(pointer(rename = "error"))]
ErrorResponse { message: String },
}
let success = ApiResponse::SuccessResponse {
data: "ok".to_owned(),
};
let data: &str = success.pointer("/success_response/data")?;
assert_eq!(data, "ok");
let error = ApiResponse::ErrorResponse {
message: "failed".to_owned(),
};
let message: &str = error.pointer("/error/message")?;
assert_eq!(message, "failed");
# Ok(())
# }
Enum representations
Like Serde, #[derive(JsonPointee)] supports externally tagged,
internally tagged, adjacently tagged, and untagged enum representations.
Externally tagged
This is the default enum representation. The variant's tag wraps the contents.
# use ploidy_pointer::{JsonPointerTarget, JsonPointee, JsonPointeeExt};
# fn main() -> Result<(), Box<dyn std::error::Error>> {
#[derive(JsonPointee, JsonPointerTarget)]
enum Message {
Text { content: String },
Image { url: String },
}
let message = Message::Text {
content: "hello".to_owned(),
};
let content: &str = message.pointer("/Text/content")?;
assert_eq!(content, "hello");
# Ok(())
# }
Internally tagged
In this representation, the tag that specifies the variant name is next to the variant's fields.
# use ploidy_pointer::{JsonPointerTarget, JsonPointee, JsonPointeeExt};
# fn main() -> Result<(), Box<dyn std::error::Error>> {
#[derive(JsonPointee, JsonPointerTarget)]
#[ploidy(pointer(tag = "type"))]
enum Message {
Text { content: String },
Image { url: String },
}
let message = Message::Text {
content: "hello".to_owned(),
};
let tag: &str = message.pointer("/type")?;
assert_eq!(tag, "Text");
let content: &str = message.pointer("/content")?;
assert_eq!(content, "hello");
# Ok(())
# }
Adjacently tagged
In this representation, the variant's tag and contents are adjacent to each other, as two fields in the same object.
# use ploidy_pointer::{JsonPointerTarget, JsonPointee, JsonPointeeExt};
# fn main() -> Result<(), Box<dyn std::error::Error>> {
#[derive(JsonPointee, JsonPointerTarget)]
#[ploidy(pointer(tag = "type", content = "value"))]
enum Message {
Text { content: String },
Image { url: String },
}
let message = Message::Text {
content: "hello".to_owned(),
};
let tag: &str = message.pointer("/type")?;
assert_eq!(tag, "Text");
let content: &str = message.pointer("/value/content")?;
assert_eq!(content, "hello");
# Ok(())
# }
Untagged
In this representation, the variant's name is completely ignored, and pointers are resolved against the variant's contents.
# use ploidy_pointer::{JsonPointerTarget, JsonPointee, JsonPointeeExt};
# fn main() -> Result<(), Box<dyn std::error::Error>> {
#[derive(JsonPointee, JsonPointerTarget)]
#[ploidy(pointer(untagged))]
enum Message {
Text { content: String },
Image { url: String },
}
let message = Message::Text {
content: "hello".to_owned(),
};
let content: &str = message.pointer("/content")?;
assert_eq!(content, "hello");
# Ok(())
# }
ploidy-pointer-derive
This crate provides a derive macro for automatically implementing the JsonPointee trait from the ploidy-pointer crate. For more details about how the macro works, and how to customize the derived implementation, please see the crate docs.
Note: You typically don't need to depend on this crate directly. Instead, please use ploidy-pointer, and enable its derive feature.
Dependencies
~0.5–1MB
~20K SLoC