Rust中TOML反序列化遇缺失字段与类型不匹配错误排查
问题:TOML配置反序列化为Rust结构体失败
尝试将TOML配置文件读取到自定义的Rust配置结构体时,遇到序列化错误无法定位。先后使用config-rs(crate名为config)和toml包进行反序列化,均出现错误:
- 初始错误:
missing field: parent_url - 更新TOML文件后错误:
invalid type: map, expected a sequence
已知错误来自serde::deserialize,但无法确定代码问题。创建test_conf Cargo项目,复制以下文件即可复现问题。
src/main.rs
pub mod configuration; use toml::de::Error; use configuration::config::Setting; use configuration::test_model::TestConfig; fn main() -> Result<(), Error> { let path = String::from("test.toml"); // let content = std::fs::read_to_string(&path); // match content { // Ok(s) => { // let config: TestConfig = toml::from_str(&s)?; // }, // Err(e) => { // panic!("failed: {}", e); // } // } let site = Setting::new(path); Ok(()) }
src/configuration/config.rs
use config::{Config, File, FileFormat}; use std::string::String; use crate::configuration::test_model::TestConfig; pub struct Setting { pub config_path: String, configs: TestConfig, } impl Setting { pub fn new(config_file: String) -> Self { let parent = "src/configuration"; let config_file_path = [parent, config_file.as_str()].join("/"); let config_map: TestConfig = Setting::build_configs(config_file_path.clone()); Setting { config_path: config_file_path, configs: config_map, } } // internal functions fn build_configs(config_path: String) -> TestConfig // where // T: Setup, { let config_parser = Config::builder() .add_source(File::new(&config_path, FileFormat::Toml)) .build(); match config_parser { Ok(parser) => { let conf = parser.try_deserialize::<TestConfig>(); match conf { Ok(settings) => return settings, Err(ce) => { eprintln!("configuration parsing error: {}", ce); std::process::exit(1); } } } Err(ce) => { eprintln!("Building configuration parser failed: {}", ce); std::process::exit(1); } } } }
src/configuration/test_model.rs
use serde::{Serialize, Deserialize}; use std::vec::Vec; #[derive(Serialize, Deserialize, Debug)] pub struct TestConfig { pub parent_url: String, pub parent_folder: String, pub headers: Vec<Header>, pub things: Vec<Thing>, } #[derive(Serialize, Deserialize, Debug)] pub struct Header { pub header_name: String, pub header_value: String, } #[derive(Serialize, Deserialize, Debug)] pub struct Thing { pub base_name: String, pub place: String, pub requests: Vec<Request>, } #[derive(Serialize, Deserialize, Debug)] pub struct Request { pub name: String, pub item_name: String, pub payload: Payload, } #[derive(Serialize, Deserialize, Debug)] #[allow(non_snake_case)] pub struct Payload { pub lists: String, pub fields: String, pub hasOption: String, pub limit: String, }
src/configuration/test.toml
parent_url = "initial url" parent_folder = "/home/some/path" [headers] [headers.accept] header_name = "accept" header_value = "application/json" [headers.encoding] header_name = "accept-encoding" header_value = "gzip, deflate, br, zstd" [headers.language] header_name = "accept-language" header_value = "en-GB;q=0.5" [headers.referer] header_name = "referer" header_value = "www.com" [headers.agent] header_name = "user-agent" header_value = "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/127.0" [headers.authority] header_name = "authority" header_value = "www.com" [thing] base_name = "base_url" place = "test_folder" [[thing.requests]] name = "test_name_one" item_name = "local_test_one_file.json" [thing.requests.payload] lists = "test" fields = "symbol,symbolName" hasOption = "true" limit = "100" [[thing.requests]] name = "test_name_two" item_name = "local_test_two_file.json" [thing.requests.payload] lists = "test" fields = "symbol,symbolName" hasOption = "true" limit = "100"
src/configuration/model.rs
pub mod config; pub mod test_model;
Cargo.toml
[package] name = "test_conf" version = "0.1.0" edition = "2021" [[bin]] name = "test_conf" test = false bench = false [dependencies] reqwest = { version = "0.12.5", features = ["blocking", "gzip", "json", "cookies"] } tokio = { version = "1.38.0", features = ["full"] } futures = { version = "0.3.30", features = ["executor"] } reqwest_cookie_store = "0.8.0" serde = { version = "1.0.203", features = ["derive"] } serde_json = { version = "1.0.117" } urlencoding = { version = "2.1.3" } config = { version = "0.14.0", features = ["toml", "ini"]} toml = { version = "0.8.14" }
内容的提问来源于stack exchange,提问作者stucash
相关产品推荐
相关产品推荐

