让我们考虑以下示例代码(我的实际代码有十分之几的字段):

fn empty_field() -> Result<f64, String> {
    Err(String::new())
}

#[derive(Deserialize, Serialize)]
struct Record {
    #[serde(rename = "Apple", default)]
    a: f64,
    #[serde(rename = "Banana", default)]
    b: String,
    #[serde(rename = "Coconut", default = "empty_field")]
    c: Result<f64, String>,
}

是否可以获得基于Serde注释的默认实例,而无需手动定义,如下所示?

let empty_record = Record {
    a: 0.0,
    b: String::new(),
    c: Err(String::new()),
};

推荐答案

您可以直接从空的HashMap反序列化.

use serde::{
    de::value::{Error as SerdeError, MapDeserializer},
    Deserialize, Serialize,
}; // 1.0.193
use std::collections::HashMap;
use std::error::Error;

// your definitions here

fn main() -> Result<(), Box<dyn Error>> {
    let data = HashMap::<(), ()>::new(); // K, V types seem not to matter
    let record = Record::deserialize(MapDeserializer::<_, SerdeError>::new(data.into_iter()))?;
    println!("{record:?}");
    Ok(())
}
Record { a: 0.0, b: "", c: Err("") }

Rust相关问答推荐

如何使用Match比较 struct 中的值

在Rust中赋值变量有运行时开销吗?

使用模块中的所有模块,但不包括特定模块

在本例中,为什么我不能一次多次borrow 可变变量?

如何强制匹配的返回类型为()?

仅发布工作区的二进制 crate

unwrap 选项类型出现错误:无法移出共享引用后面的*foo

Option<&T> 如何实现复制

如何为已实现其他相关 std trait 的每个类型实现一个 std Trait

Rust编译器通过哪些规则来确保锁被释放?

将原始可变指针传递给 C FFI 后出现意外值

在 Rust 中,将可变引用传递给函数的机制是什么?

使用 HashMap 条目时如何避免字符串键的短暂克隆?

当我不满足特征界限时会发生什么?

在 FFI 的上下文中,未初始化是什么意思?

有没有办法隐藏类型定义?

您如何使用枚举反序列化字符串,其中任何其他值反序列化为新类型变体同时保留字符串?

为什么我可以在没有生命周期问题的情况下内联调用 iter 和 collect?

为什么 `ref` 会导致此示例*取消引用*一个字段?

为什么可以从不可变 struct 的字段中移动?