You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Option<String>创建Serde反序列化器以测试自定义函数?

问题:测试处理Option<String>的serde自定义反序列化函数

我有两个用于serde deserialize_with的自定义函数:

// Converts string to u32
pub fn de_u32_from_str<'de, D>(deserializer: D) -> Result<u32, D::Error>
where
    D: Deserializer<'de>,
{
    let s = String::deserialize(deserializer)?;
    s.parse::<u32>().map_err(de::Error::custom)
}

// Converts string that may be `null` to either `Some(u32)` or `None`
pub fn de_opt_u32_from_opt_str<'de, D>(deserializer: D) -> Result<Option<u32>, D::Error>
where
    D: Deserializer<'de>,
{
    let s = Option::<String>::deserialize(deserializer)?;
    s.map(|s| s.parse::<u32>().map_err(de::Error::custom))
        .transpose()
}

我已通过以下方式测试de_u32_from_str:

fn deserialize_u32_from_str(string: &str, expected: u32) {
    let de: StrDeserializer<ValueError> = string.into_deserializer();
    let result = de_u32_from_str(de).unwrap();

    assert_eq!(result, expected);
}

但在测试de_opt_u32_from_opt_str时,我无法创建合适的反序列化器:

fn deserialize_opt_u32_from_opt_str(maybe_string: Option<&str>, expected: Option<u32>) {
    // I need a `deserializer` here
    let de: ... = ...;
    let result = de_opt_u32_from_opt_str(de).unwrap();

    assert_eq!(result, expected);
}

请问如何创建类似let de: StrDeserializer<ValueError> = string.into_deserializer();的反序列化器,但该反序列化器可承载Option<String>,以满足let s = Option::<String>::deserialize(deserializer)?;的需求?


解决方案

方法1:直接利用Option<&str>的IntoDeserializer实现

Option<T>本身实现了IntoDeserializer trait(只要T实现了该trait),所以你可以直接将Option<&str>转换成符合要求的反序列化器:

use serde::de::{Deserializer, IntoDeserializer};
use serde::Deserialize;
use serde::de::value::ValueError;

fn deserialize_opt_u32_from_opt_str(maybe_string: Option<&str>, expected: Option<u32>) {
    let de = maybe_string.into_deserializer();
    let result = de_opt_u32_from_opt_str(de).unwrap();

    assert_eq!(result, expected);
}

这个方式能直接覆盖两种场景:当输入是Some("123")时,反序列化器会解析为Some(String);当输入是None时,反序列化器会解析为None。

方法2:用serde_json模拟真实JSON场景

如果需要贴近实际的JSON反序列化逻辑(比如明确处理null值),可以用serde_json::Value构建反序列化器:

use serde_json::Value;
use serde::de::Deserializer;

fn deserialize_opt_u32_from_opt_str(maybe_string: Option<&str>, expected: Option<u32>) {
    let json_value = match maybe_string {
        Some(s) => Value::String(s.to_string()),
        None => Value::Null,
    };
    let de = json_value.into_deserializer();
    let result = de_opt_u32_from_opt_str(de).unwrap();

    assert_eq!(result, expected);
}

这种方式更符合真实业务中JSON数据的解析场景,能准确模拟null和字符串两种输入情况。

完整测试用例示例

可以编写测试覆盖所有分支:

#[test]
fn test_opt_u32_from_opt_str() {
    // 测试有效字符串转Some(u32)
    deserialize_opt_u32_from_opt_str(Some("456"), Some(456));
    // 测试None转None
    deserialize_opt_u32_from_opt_str(None, None);
    // 测试无效字符串的错误分支
    let de = Some("not_a_number").into_deserializer();
    assert!(de_opt_u32_from_opt_str(de).is_err());
}

内容的提问来源于stack exchange,提问作者Slava.In

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 21:02:24