使用config-rs反序列化TOML字符串以枚举 [英] Deserialize TOML string to enum using config-rs
问题描述
我正在使用config-rs从TOML文件中加载配置,我想将字符串反序列化为枚举.我尝试使用serde_derive的deserialize_with
功能解决它,但是我不知道如何返回合适的Error来满足函数签名.我该如何实现?
I'm using config-rs to load the configuration from a TOML file and I want to deserialize a string to an enum. I tried to solve it using the deserialize_with
feature of serde_derive but I don't know how to return a suitable Error to satisfy the function signature. How can I achieve it?
我的依赖项:
config = "0.7"
serde_derive = "1.0"
serde = "1.0"
toml = "0.4"
用于反序列化枚举RotationPolicyType
的示例代码:
Example code where it's intended to deserialize the enum RotationPolicyType
:
extern crate config;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate toml;
use std::env;
use config::{Config, Environment, File};
use std::path::PathBuf;
use serde;
use serde::de::Deserializer;
use serde::Deserialize;
#[derive(Debug, Deserialize, Clone)]
pub enum RotationPolicyType {
ByDuration,
ByDay,
}
#[derive(Debug, Deserialize, Clone)]
pub struct FileConfig {
pub rotations: i32,
#[serde(deserialize_with="deserialize_with")]
pub rotation_policy_type: RotationPolicyType,
}
#[derive(Debug, Deserialize, Clone)]
pub struct Settings {
pub threads: usize,
pub file_writer: FileConfig,
}
impl Settings {
pub fn new() -> Self {
let mut s = Config::new();
s.merge(File::with_name("config/default")).unwrap();
s.merge(File::with_name("config/local").required(false))
.unwrap();
s.merge(Environment::with_prefix("app")).unwrap();
s.deserialize().unwrap()
}
}
fn deserialize_with<D>(deserializer: D) -> Result<RotationPolicyType, D::Error> where D: Deserializer {
let s = String::deserialize(deserializer)?;
match s.as_ref() {
"ByDuration" => Ok(RotationPolicyType::ByDuration),
"ByDay" => Ok(RotationPolicyType::ByDay),
_ => Err(serde::de::Error::custom("error trying to deserialize rotation policy config"))
}
}
fn deserialize_with2<'de, D>(deserializer: &'de mut D) -> Result<RotationPolicyType, D::Error> where &'de mut D: Deserializer<'de> {
let s = String::deserialize(deserializer)?;
match s.as_ref() {
"ByDuration" => Ok(RotationPolicyType::ByDuration),
"ByDay" => Ok(RotationPolicyType::ByDay),
_ => Err(serde::de::Error::custom("error trying to deserialize rotation policy config"))
}
}
使用 deserialize_with 的编译错误:
error[E0106]: missing lifetime specifier
--> src/settings.rs:30:94
|
30 | fn deserialize_with<D>(deserializer: D) -> Result<RotationPolicyType, D::Error> where D: Deserializer {
| ^^^^^^^^^^^^ expected lifetime parameter
error: aborting due to previous error
deserialize_with2 的编译错误:
error[E0220]: associated type `Error` not found for `D`
--> src/settings.rs:42:90
|
42 | fn deserialize_with2<'de, D>(deserializer: &'de mut D) -> Result<RotationPolicyType, D::Error> where &'de mut D: Deserializer<'de> {
| ^^^^^^^^ associated type `Error` not found
error: aborting due to previous error
推荐答案
首先,您的示例编译得不够充分,无法得到您所描述的错误.请注意下次生成 MCVE .使其在 https://play.rust-lang.org (即可能,在您的示例中完全不需要extern crate config
.
First of all, your example does not compile far enough to get to the errors you are describing. Please take care to produce an MCVE next time. Bonus points for getting it to work on https://play.rust-lang.org (which is possible, the extern crate config
is entirely unnecessary in your example).
After fixing up all the compilation issues, your first error is simply fixed by changing the function API to match the one suggested in the serde docs
-fn deserialize_with< D>(deserializer: D) -> Result<RotationPolicyType, D::Error> where D: Deserializer
+fn deserialize_with<'de, D>(deserializer: D) -> Result<RotationPolicyType, D::Error> where D: Deserializer<'de>
该错误试图帮助您.它告诉您Deserializer
缺少生存期参数.
The error tried to help you there. It told you that Deserializer
is missing a lifetime parameter.
第二个功能告诉您D
没有关联的类型Error
.它只有在D
将实现Deserializer<'de>
时才能具有.但是您指定了&'de mut D
实现Deserializer<'de>
.寻找解决此问题的方法留给读者练习.
The second function is telling you that D
has no associated type Error
. Which it can only have if D
would implement Deserializer<'de>
. But you specified that &'de mut D
implements Deserializer<'de>
. Finding the solution to this problem is left as an exercise to the reader.
这篇关于使用config-rs反序列化TOML字符串以枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!