| Crates.io | field_name |
| lib.rs | field_name |
| version | 0.2.0 |
| created_at | 2025-12-23 12:43:09.728647+00 |
| updated_at | 2025-12-23 12:50:13.367768+00 |
| description | A proc-macro for exposing a struct's field names at runtime. |
| homepage | |
| repository | https://github.com/h01-team/field_name |
| max_upload_size | |
| id | 2001453 |
| size | 20,216 |
Stop hardcoding strings. Start using the type system.
We've all been there. You're writing a MongoDB query, a raw SQL statement, or some custom JSON patch logic. You type "user_name" into your query builder. Later, you refactor your Rust struct to use username.
The code compiles. The tests pass (mostly). But in production, your query returns nothing because the string literal didn't update itself.
field_name fixes this by making your field names available as compile-time constants.
// ❌ The "Stringly Typed" Way
// If you rename `id` to `uuid` in the struct, this line acts like nothing happened.
// You won't know it's broken until runtime.
let query = doc! { "_id": "12345" };
// ✅ The "Strongly Typed" Way
// If you rename `id` to `uuid` in the struct, this won't compile.
// You catch the bug immediately.
let query = doc! { User::ID: "12345" };
Add this to your Cargo.toml:
[dependencies]
field_name = "0.2"
Just derive FieldNames. It generates a public constant for every field (uppercased) and a FIELDS array containing all of them.
use field_name::FieldNames;
#[derive(FieldNames)]
struct User {
// 1. Rename support: Map Rust's "id" to Mongo's "_id"
#[field_name(rename = "_id")]
id: u64,
username: String,
// 2. Skip support: Don't generate constants for internal fields
#[field_name(skip)]
password_hash: String,
}
fn main() {
// Use the individual constants for queries
assert_eq!(User::ID, "_id");
assert_eq!(User::USERNAME, "username");
// Use the list for validation or schema generation
assert_eq!(User::FIELDS, ["_id", "username"]);
// Attempting to access User::PASSWORD_HASH will fail to compile!
}
Derive VariantNames to get string representations of your variants without instantiating them.
use field_name::VariantNames;
#[derive(VariantNames)]
enum Status {
Pending,
#[variant_name(rename = "in_progress")]
Processing,
Completed,
}
fn main() {
assert_eq!(Status::PENDING, "Pending");
assert_eq!(Status::PROCESSING, "in_progress");
// Great for logging or quick checks
if some_api_string == Status::PROCESSING {
println!("We are moving!");
}
}
Serde is amazing for serialization, but it doesn't expose the names of the fields as constants you can use in code. If you need to construct a dictionary, a specific SQL query, or a dynamic generic function that iterates over valid field names, Serde can't help you there. field_name fills that gap.
| Attribute | Where? | What it does |
|---|---|---|
#[field_name(rename = "x")] |
Struct Field | Changes the constant value to "x". Useful for _id or camelCase APIs. |
#[field_name(skip)] |
Struct Field | Ignores this field. No constant or array entry will be generated. |
#[variant_name(rename = "x")] |
Enum Variant | Same as above, but for Enums. |
#[variant_name(skip)] |
Enum Variant | Same as above, but for Enums. |
MIT. Do whatever you want with it. Happy coding!