Rust如何通过字符串key获取struct值及将struct转为数组
Rust 中通过字符串key读取struct字段及struct转数组解决方案
首先先纠正你示例代码的笔误:你原有代码里的impl块写的是impl Structure,返回类型也是Structure,实际应该对应Messages结构体。
一、通过字符串key读取struct字段
Rust默认不支持用字符串下标直接访问struct字段,因为struct字段是编译期确定的静态结构,字符串是运行期动态值,需要手动实现对应逻辑,有两种常见方案:
方案1:手动实现Index trait,直接支持[]下标访问
这种写法完全符合你示例中的messages["greetings"]调用方式,适合字段少的结构体:
use std::ops::Index; struct Messages { greetings: String, goodbyes: String } impl Messages { fn new() -> Self { Messages { greetings: String::from("Hello world"), goodbyes: String::from("Bye!") } } // 不需要panic的话可以额外加这个方法,匹配不到返回None fn get(&self, key: &str) -> Option<&str> { match key { "greetings" => Some(&self.greetings), "goodbyes" => Some(&self.goodbyes), _ => None } } } // 实现Index trait支持[]运算符 impl Index<&str> for Messages { type Output = str; fn index(&self, key: &str) -> &Self::Output { match key { "greetings" => &self.greetings, "goodbyes" => &self.goodbyes, _ => panic!("不存在字段:{}", key) } } } fn main() { let messages = Messages::new(); println!("{}", messages["greetings"]); // 输出 Hello world println!("{}", messages.get("goodbyes").unwrap()); // 输出 Bye! }
方案2:借助serde转成动态集合,适合字段多的结构体
如果结构体字段很多,手写match太繁琐,可以用serde做序列化转成HashMap或者动态值,不需要手写每个字段的匹配逻辑,先在Cargo.toml中添加依赖:
serde = { version = "1.0", features = ["derive"] } serde_json = "1.0"
实现代码:
use serde::Serialize; use std::collections::HashMap; #[derive(Serialize)] struct Messages { greetings: String, goodbyes: String } impl Messages { fn new() -> Self { Messages { greetings: String::from("Hello world"), goodbyes: String::from("Bye!") } } } fn main() { let messages = Messages::new(); // 直接转成HashMap通过字符串key取值 let map: HashMap<String, String> = serde_json::from_value(serde_json::to_value(messages).unwrap()).unwrap(); println!("{}", map.get("greetings").unwrap()); // 输出 Hello world }
二、将struct转为键值对数组
你示例中的to_array需求可以通过手动实现,下面的版本返回存储「字段名+字段值」的数组:
struct Messages { greetings: String, goodbyes: String } impl Messages { fn new() -> Self { Messages { greetings: String::from("Hello world"), goodbyes: String::from("Bye!") } } fn to_array(&self) -> [(&str, &str); 2] { [ ("greetings", &self.greetings), ("goodbyes", &self.goodbyes) ] } } fn main() { let messages = Messages::new(); let arr = messages.to_array(); // 遍历输出所有字段 for (key, value) in arr { println!("{}: {}", key, value); } }
如果结构体字段类型不一致,可以把值的类型换成serde_json::Value或者自定义枚举来存储不同类型的值。
内容的提问来源于stack exchange,提问作者Siriusmart
相关产品推荐
相关产品推荐

