我想用 struct 作为键序列化HashMap:

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

fn main() {
    #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]
    struct Foo {
        x: u64,
    }

    #[derive(Serialize, Deserialize, Debug)]
    struct Bar {
        x: HashMap<Foo, f64>,
    }

    let mut p = Bar { x: HashMap::new() };
    p.x.insert(Foo { x: 0 }, 0.0);
    let serialized = serde_json::to_string(&p).unwrap();
}

这段代码可以编译,但当我运行它时,会出现一个错误:

Error("key must be a string", line: 0, column: 0)'

我更改了密码:

#[derive(Serialize, Deserialize, Debug)]
struct Bar {
    x: HashMap<u64, f64>,
}

let mut p = Bar { x: HashMap::new() };
p.x.insert(0, 0.0);
let serialized = serde_json::to_string(&p).unwrap();

HashMap中的键现在是u64而不是字符串.为什么第一个代码会给出错误?

推荐答案

根据JSONs specification,JSON键必须是字符串.serde_jsonsome个非字符串键使用fmt::Display in here,以允许更大范围的HashMap的序列化.这就是为什么HashMap<u64, f64>HashMap<String, f64>的效果一样好.然而,并不是所有类型都包括在内(Foo's case here).

这就是为什么我们需要提供自己的Serialize个实现:

impl Display for Foo {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "{}", self.x)
    }
}

impl Serialize for Bar {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut map = serializer.serialize_map(Some(self.x.len()))?;
        for (k, v) in &self.x {
            map.serialize_entry(&k.to_string(), &v)?;
        }
        map.end()
    }
}

(playground)

Rust相关问答推荐

如何使用字符串迭代器执行查找?

为什么BitVec缺少Serialize trait?

rust 迹-内存管理-POP所有权-链表

铁 rust 中的共享对象实现特征

无法定义名为&new&的关联函数,该函数的第一个参数不是self

为什么基于高山Linux的Docker镜像不能在绝对路径下找到要执行的命令?

我是否可以在Ruust中修改 struct 实例上的字符串,以使其在修改后具有相同的字符串生存期?

从未排序的链表中删除重复项的铁 rust 代码在ELSE分支的低级上做了什么?

如何在不调用Collect()的情况下为新型vec实现IntoIterator?

Rust函数的返回值不能引用局部变量或临时变量

返回迭代器考虑静态生命周期类型

闭包返回类型的生命周期规范

使用在功能标志后面导入的类型,即使未启用功能标志

在运行时在 Rust 中加载字体

为什么 Rust 允许写入不可变的 RwLock?

如何存储返回 Future 的闭包列表并在 Rust 中的线程之间共享它?

在使用大型表达式时(8k 行需要一小时编译),是否可以避免 Rust 中的二次编译时间?

有没有办法在 Rust 中对 BigInt 进行正确的位移?

为什么我不能为 Display+Debug 的泛型类型实现 std::error::Error 但有一个不是泛型参数的类型?

Rust 中的运行时插件