-
-
Notifications
You must be signed in to change notification settings - Fork 774
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Get the field names of a struct #1110
Labels
Comments
This is a somewhat unconventional use case for Serde but the following gives a #[macro_use] extern crate serde;
#[macro_use] extern crate serde_derive;
use serde::de::{self, Deserialize, Deserializer, Visitor};
#[derive(Deserialize)]
struct AuthError {
error: String,
description: String
}
fn struct_fields<'de, T>() -> &'static [&'static str]
where T: Deserialize<'de>
{
struct StructFieldsDeserializer<'a> {
fields: &'a mut Option<&'static [&'static str]>,
}
impl<'de, 'a> Deserializer<'de> for StructFieldsDeserializer<'a> {
type Error = serde::de::value::Error;
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor<'de>
{
Err(de::Error::custom("I'm just here for the fields"))
}
fn deserialize_struct<V>(
self,
_name: &'static str,
fields: &'static [&'static str],
visitor: V
) -> Result<V::Value, Self::Error>
where V: Visitor<'de>
{
*self.fields = Some(fields);
self.deserialize_any(visitor)
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map enum identifier ignored_any
}
}
let mut fields = None;
let _ = T::deserialize(StructFieldsDeserializer { fields: &mut fields });
fields.unwrap()
}
fn main() {
// prints ["error", "description"]
println!("{:?}", struct_fields::<AuthError>());
} |
Practically the same code but for enum variant names: #[macro_use] extern crate serde;
#[macro_use] extern crate serde_derive;
use serde::de::{self, Deserialize, Deserializer, Visitor};
#[derive(Deserialize)]
#[serde(rename_all = "lowercase")]
enum Setting { On, Off }
fn enum_variants<'de, T>() -> &'static [&'static str]
where T: Deserialize<'de>
{
struct EnumVariantsDeserializer<'a> {
variants: &'a mut Option<&'static [&'static str]>,
}
impl<'de, 'a> Deserializer<'de> for EnumVariantsDeserializer<'a> {
type Error = serde::de::value::Error;
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor<'de>
{
Err(de::Error::custom("I'm just here for the variants"))
}
fn deserialize_enum<V>(
self,
_name: &'static str,
variants: &'static [&'static str],
visitor: V
) -> Result<V::Value, Self::Error>
where V: Visitor<'de>
{
*self.variants = Some(variants);
self.deserialize_any(visitor)
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct identifier ignored_any
}
}
let mut variants = None;
let _ = T::deserialize(EnumVariantsDeserializer { variants: &mut variants });
variants.unwrap()
}
fn main() {
// prints ["on", "off"]
println!("{:?}", enum_variants::<Setting>());
} |
Seems like something that should be in serde-aux |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A question from u.r-l.o: how to get a slice of field names for an arbitrary struct type T?
The text was updated successfully, but these errors were encountered: