【问题标题】:How to serialize/deserialize a map with the None values如何使用 None 值序列化/反序列化地图
【发布时间】:2021-09-30 16:04:26
【问题描述】:

我需要在我的配置中包含Option 值的地图。但是,serde 似乎忽略了具有 None 值的任何对

use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use toml;

#[derive(Debug, Serialize, Deserialize)]
struct Config {
    values: HashMap<String, Option<u32>>,
}

fn main() {
    let values = [("foo", Some(5)), ("bar", None)]
        .iter()
        .map(|(name, s)| (name.to_string(), s.clone()))
        .collect();
    let config = Config { values };

    let s = toml::ser::to_string(&config).unwrap();
    println!("{}", s);
}

生产

[values]
foo = 5

反序列化也是如此:我根本无法以任何形式表示bar: None, 因为 TOML 没有 Nonenull 或类似的概念。

有没有一些技巧可以做到这一点?

【问题讨论】:

  • 不是一个“技巧”,但您可以编写一个自定义序列化程序,然后将其附加到 values#[serde(serialize_with = "my_serializer")]
  • 您希望输出是什么? TOML 的设计不允许分配 null/None 类型的值。你要它干什么?
  • Serde 受到您使用的文件格式的限制。 Toml 没有 None 的概念,因此 serde 无法在 Toml 文件中表示它。您需要切换到可以表示None 的格式(例如JSON)或使用自定义(反)序列化器来告诉serde 您想如何在Toml 中表示None

标签: rust serde toml


【解决方案1】:

我找到的最接近的替代方法是使用一个特殊的标记值(您可能会在 Option::unwrap_or 中使用的那个),它作为实际值出现在 TOML 文件中(例如 0),并从 @ 转换987654324@ 关于序列化。但是在反序列化时,哨兵值会转换为 Option::None 并留给我们真正的 Option 类型。

Serde 有一个特殊的 #[serde(with = module)] 属性来自定义 ser/de 字段行为,您可以在此处使用该属性。完整的工作示例是here

【讨论】:

    猜你喜欢
    • 2017-11-20
    • 1970-01-01
    • 1970-01-01
    • 2020-08-24
    • 1970-01-01
    • 2015-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多