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

如何通过wasm-bindgen将带id的嵌套Rust结构体转为TS扁平对象

解决Rust嵌套结构体转TS扁平对象的方法

针对你用wasm-bindgen在Rust与TypeScript间传递数据时,需要将嵌套的InvoiceWithId结构体转换为TS扁平对象的需求,下面提供三种可行方案:

方案一:手动构建JS对象

直接在Rust中利用js_sys或wasm_bindgen::JsValue手动创建符合TS结构的扁平对象:

use wasm_bindgen::prelude::*;
use js_sys::Object;

#[wasm_bindgen]
pub struct InvoiceSchema {
    pub bill_to: String,
    pub email: String,
}

#[wasm_bindgen]
pub struct InvoiceWithId {
    pub id: String,
    pub schema: InvoiceSchema,
}

#[wasm_bindgen]
impl InvoiceWithId {
    pub fn to_flat_js_object(&self) -> JsValue {
        let obj = Object::new();
        // 设置id属性
        js_sys::Reflect::set(&obj, &"id".into(), &self.id.into()).unwrap();
        // 设置billTo属性
        js_sys::Reflect::set(&obj, &"billTo".into(), &self.schema.bill_to.into()).unwrap();
        // 设置email属性
        js_sys::Reflect::set(&obj, &"email".into(), &self.schema.email.into()).unwrap();
        obj.into()
    }
}

在TypeScript中直接调用该方法就能得到扁平对象:

import { InvoiceWithId } from "./your-wasm-module";

const invoice = new InvoiceWithId("123", { bill_to: "Alice", email: "alice@example.com" });
const flatInvoice = invoice.to_flat_js_object();
// flatInvoice 结构为 { id: "123", billTo: "Alice", email: "alice@example.com" }

方案二:使用Serde自定义序列化

通过Serde的序列化特性,给InvoiceWithId实现自定义的Serialize逻辑,将嵌套字段扁平化:

首先确保Cargo.toml中添加依赖:

[dependencies]
wasm-bindgen = { version = "0.2", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

然后修改Rust代码:

use wasm_bindgen::prelude::*;
use serde::Serialize;

#[wasm_bindgen]
#[derive(Serialize)]
pub struct InvoiceSchema {
    #[serde(rename = "billTo")]
    pub bill_to: String,
    pub email: String,
}

#[wasm_bindgen]
pub struct InvoiceWithId {
    pub id: String,
    pub schema: InvoiceSchema,
}

#[wasm_bindgen]
impl InvoiceWithId {
    pub fn to_flat_json(&self) -> JsValue {
        // 自定义序列化逻辑,合并字段
        let flat_obj = serde_json::json!({
            "id": self.id,
            "billTo": self.schema.bill_to,
            "email": self.schema.email
        });
        flat_obj.into()
    }
}

TypeScript中调用后直接使用即可,无需额外转换。

方案三:利用Serde的flatten属性

如果允许调整Rust结构体的定义方式,可以给嵌套字段加上#[serde(flatten)]属性,让Serde自动扁平化输出:

use wasm_bindgen::prelude::*;
use serde::Serialize;

#[wasm_bindgen]
#[derive(Serialize)]
pub struct InvoiceSchema {
    #[serde(rename = "billTo")]
    pub bill_to: String,
    pub email: String,
}

#[wasm_bindgen]
#[derive(Serialize)]
pub struct InvoiceWithId {
    pub id: String,
    #[serde(flatten)]
    pub schema: InvoiceSchema,
}

#[wasm_bindgen]
impl InvoiceWithId {
    pub fn to_js_value(&self) -> JsValue {
        JsValue::from_serde(self).unwrap()
    }
}

这种方式最简洁,序列化后直接得到TS所需的扁平对象,无需手动拼接字段。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 17:12:35