Here is another feature that does not require a macro record (however field names will be resolved at runtime):
extern crate rustc_serialize; use rustc_serialize::json::{Encoder, Json}; use rustc_serialize::json::Json::Object; use rustc_serialize::Encodable; #[derive(Default, RustcEncodable)] struct S { a: String, b: String, } fn main() { let mut json = "".to_owned(); { let mut encoder = Encoder::new(&mut json); S::default().encode(&mut encoder).unwrap(); } let json = Json::from_str(&json).unwrap(); if let Object(object) = json { let field_names: Vec<_> = object.keys().collect(); println!("{:?}", field_names); } }
(for this solution you need a rustc-serialize box)
derive(Default) added to avoid the need to manually create the structure as you wish (but the structure will still be created).
This solution works by encoding a structure in String format in JSON format and decoding it to Json . From the Json object Json we can extract the field names (if it is a variant of Object ).
Perhaps a more efficient way is to create your own encoder:
struct FieldNames { names: Vec<String>, } impl FieldNames { fn new() -> FieldNames { FieldNames { names: vec![], } } } struct FieldsEncoder<'a> { fields: &'a mut FieldNames, } impl<'a> FieldsEncoder<'a> { fn new(fields: &mut FieldNames) -> FieldsEncoder { FieldsEncoder { fields: fields, } } } type EncoderError = (); impl<'a> Encoder for FieldsEncoder<'a> { fn emit_struct<F>(&mut self, _name: &str, _len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) } fn emit_struct_field<F>(&mut self, f_name: &str, _f_idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { self.fields.names.push(f_name.to_owned()); Ok(()) } type Error = EncoderError; fn emit_nil(&mut self) -> Result<(), Self::Error> { Err(()) } fn emit_usize(&mut self, _v: usize) -> Result<(), Self::Error> { Err(()) } fn emit_u64(&mut self, _v: u64) -> Result<(), Self::Error> { Err(()) } fn emit_u32(&mut self, _v: u32) -> Result<(), Self::Error> { Err(()) } fn emit_u16(&mut self, _v: u16) -> Result<(), Self::Error> { Err(()) } fn emit_u8(&mut self, _v: u8) -> Result<(), Self::Error> { Err(()) } fn emit_isize(&mut self, _v: isize) -> Result<(), Self::Error> { Err(()) } fn emit_i64(&mut self, _v: i64) -> Result<(), Self::Error> { Err(()) } fn emit_i32(&mut self, _v: i32) -> Result<(), Self::Error> { Err(()) } fn emit_i16(&mut self, _v: i16) -> Result<(), Self::Error> { Err(()) } fn emit_i8(&mut self, _v: i8) -> Result<(), Self::Error> { Err(()) } fn emit_bool(&mut self, _v: bool) -> Result<(), Self::Error> { Err(()) } fn emit_f64(&mut self, _v: f64) -> Result<(), Self::Error> { Err(()) } fn emit_f32(&mut self, _v: f32) -> Result<(), Self::Error> { Err(()) } fn emit_char(&mut self, _v: char) -> Result<(), Self::Error> { Err(()) } fn emit_str(&mut self, _v: &str) -> Result<(), Self::Error> { Err(()) } fn emit_enum<F>(&mut self, _name: &str, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_enum_variant<F>(&mut self, _v_name: &str, _v_id: usize, _len: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_enum_variant_arg<F>(&mut self, _a_idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_enum_struct_variant<F>(&mut self, _v_name: &str, _v_id: usize, _len: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_enum_struct_variant_field<F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_tuple<F>(&mut self, _len: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_tuple_arg<F>(&mut self, _idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_tuple_struct<F>(&mut self, _name: &str, _len: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_tuple_struct_arg<F>(&mut self, _f_idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_option<F>(&mut self, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_option_none(&mut self) -> Result<(), Self::Error> { Err(()) } fn emit_option_some<F>(&mut self, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_seq<F>(&mut self, _len: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_seq_elt<F>(&mut self, _idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_map<F>(&mut self, _len: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_map_elt_key<F>(&mut self, _idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_map_elt_val<F>(&mut self, _idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } }
which can be used as such:
fn main() { let mut fields = FieldNames::new(); { let mut encoder = FieldsEncoder::new(&mut fields); S::default().encode(&mut encoder).unwrap(); } println!("{:?}", fields.names); }