使用config-rs反序列化TOML字符串以枚举 [英] Deserialize TOML string to enum using config-rs

查看:157
本文介绍了使用config-rs反序列化TOML字符串以枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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).

解决所有编译问题后,只需更改功能API以匹配建议的

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆