如何通过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
相关产品推荐
相关产品推荐

