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

使用wasm-bindgen实现双类型字段序列化的正确方案求助

解决JSON双类型字段反序列化问题

你遇到的问题根源是:serde默认的枚举反序列化逻辑要求JSON值必须带变体标签(比如{"SimpleAmount": "24789223"}),但你的接口返回的是无标签的直接字符串或对象,因此触发了未知变体的错误。以下是两种适配wasm-bindgen环境的可行方案:

方案一:使用#[serde(untagged)]属性(推荐)

给CustomAmount枚举添加#[serde(untagged)]属性,serde会自动按枚举顺序尝试匹配JSON值的类型,无需额外标签:

use serde::Deserialize;

#[derive(Deserialize, Debug)]
#[serde(untagged)] // 核心配置
pub enum CustomAmount {
    ComplexAmount(ComplexAmount),
    SimpleAmount(String),
}

#[derive(Deserialize, Debug)]
pub struct ComplexAmount {
    pub value: String,
    pub currency: String,
}

注:变体顺序不影响当前场景(字符串和对象无类型歧义),如果后续出现类型重叠,需将更具体的变体放在前面优先匹配。

方案二:手动实现Deserialize trait

若需要更精细的控制逻辑,可以手动编写反序列化代码,先判断JSON值类型再选择对应变体:

use serde::{Deserialize, Deserializer};
use serde_json::Value;

#[derive(Debug)]
pub enum CustomAmount {
    ComplexAmount(ComplexAmount),
    SimpleAmount(String),
}

#[derive(Deserialize, Debug)]
pub struct ComplexAmount {
    pub value: String,
    pub currency: String,
}

impl<'de> Deserialize<'de> for CustomAmount {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let value = Value::deserialize(deserializer)?;
        
        // 优先尝试反序列化为复杂对象
        if let Ok(complex) = ComplexAmount::deserialize(&value) {
            Ok(CustomAmount::ComplexAmount(complex))
        } else {
            // 失败则尝试转换为字符串
            let simple = String::deserialize(&value)?;
            Ok(CustomAmount::SimpleAmount(simple))
        }
    }
}

wasm-bindgen环境适配注意事项

确保Cargo.toml中已引入必要依赖:

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.6"
# 若需直接处理JSON字符串,可添加serde_json
serde_json = "1.0"

反序列化时直接使用serde_wasm_bindgen::from_value即可,两种方案均能正常适配wasm环境。

内容的提问来源于stack exchange,提问作者themonkey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 22:20:41