我正在尝试将配置
toml
文件读取到本地定义的配置结构中,并且出现了这个基本错误,但是我无法看到我实际上错过了什么。我正在使用名为 config-rs
或 config
的第 3 方板条箱(如果我们按其板条箱名称)。我还尝试单独使用 toml
包将字符串反序列化到我的配置结构中,它给了我同样的错误。
更新
missing field: parent_url
后,错误是toml
,我得到了invalid type: map, expected a sequence
的错误。
我知道这个错误很可能直接来自
serde::deserialize
,但是我无法看到我的代码是如何以及在哪里出错的。
创建一个名为
test_conf
的新货物项目,然后将以下文件复制并粘贴到该项目中将为我们提供最小的可重复性(已测试)。我刚刚开始 Rust
所以代码可能看起来写得不好。
您可能已经注意到,我们的依赖项比重现错误所需的要多
cargo.toml
;我将它们保留在那里,因为这是我遇到错误的上下文。该项目是一个稍大的项目的一部分。
编辑:更新了
toml
文件以反映评论中的建议。
// 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" }
感谢@Timsib和@kmdreko,这确实是由于无效的
toml
结构造成的。以下文件一次性修复了我的错误。
parent_url = "initial url"
parent_folder = "/home/some/path"
[[headers]]
header_name = "accept"
header_value = "application/json"
[[headers]]
header_name = "accept-encoding"
header_value = "gzip, deflate, br, zstd"
[[headers]]
header_name = "accept-language"
header_value = "en-GB;q=0.5"
[[headers]]
header_name = "referer"
header_value = "www.com"
[[headers]]
header_name = "user-agent"
header_value = "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/127.0"
[[headers]]
header_name = "authority"
header_value = "www.com"
[[things]]
base_name = "base_url"
place = "test_folder"
[[things.requests]]
name = "test_name_one"
item_name = "local_test_one_file.json"
[things.requests.payload]
lists = "test"
fields = "symbol,symbolName"
hasOption = "true"
limit = "100"
[[things.requests]]
name = "test_name_two"
item_name = "local_test_two_file.json"
[things.requests.payload]
lists = "test"
fields = "symbol,symbolName"
hasOption = "true"
limit = "100"