Expand description
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
#[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: "a@example.com".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, "a@example.com");
let phone: &str = user.pointer("/phone")?;
assert_eq!(phone, "555-1234");§Renaming fields
#[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");§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.
#[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");§Internally tagged
In this representation, the tag that specifies the variant name is next to the variant’s fields.
#[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");§Adjacently tagged
In this representation, the variant’s tag and contents are adjacent to each other, as two fields in the same object.
#[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");§Untagged
In this representation, the variant’s name is completely ignored, and pointers are resolved against the variant’s contents.
#[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");Derive Macros§
- Json
Pointee - Derives the
JsonPointeetrait for JSON Pointer (RFC 6901) traversal. - Json
Pointer Target - Derives the
JsonPointerTargettrait for downcasting a type-erasedJsonPointeereference to a concrete type reference.