How to convert JsValue to Rust struct?

Hi, I am writting the code using wasm bindgen that it querys a value from indexedDB. The type of the value from indexedDB is JsValue, how to convert it to struct in Rust, and how to convert struct in Rust to JsValue?
I know that i should implement Into trait for convertting rust struct into JsValue, and the From trait for convertting JsValue into rust struct. But i don't know the details of data structure conversion.


You can just use JsValue::from_serde() (for strong type -> JsValue) and JsValue::into_serde() (for JsValue -> strong type). That will recurse into fields and sub-objects correctly. There is no need to write any code, you can just derive Serialize and Deserialize for your domain model objects.

Also, please always post code as text, never as an image. Code that is not copiable is annoying (and outright impossible to read for the visually impaired).

2 Likes

@H2CO3 thanks, Using serde will cost time in serialization and deserialization. What if the data is a big Uint8Array, how to convert it?

Using serde doesn't necessarily mean "ser JsValue to bytes and de into T". What's happening is you are deser'ing JsValue into T directly.

Hmm, From the definition of JsValue::from_serde function, i thought it did means that using serde will serialize the rust struct into string and deserialize it into js object.
image

I made a test code, which proved this:

use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::JsValue;

#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace = console)]
    fn time(_: &str);

    #[wasm_bindgen(js_namespace = console, js_name = timeEnd)]
    fn time_end(_: &str);
}

pub fn serde_big_array() {
    let mut a = vec![];
    for i in 0..100000 {
        (&mut a).push(i);
    }
    // let a = 3;
    time("serde");
    let a_serded = JsValue::from_serde(&a);
    time_end("serde");
    if let Ok(a_serded) = a_serded {
        let t = JsValue::js_typeof(&a_serded).as_string().unwrap();
        log::info!("type of a_serded in js is: {:?}", t);
        log::info!("a_serded: {:?}", a_serded);
    }
}

The output of my web console is below:


It takes 300ms to deliver data from rust to js!

Did you have the dev tools open while running the benchmark? I believe most browsers disable (some) optimizations for wasm when the devtools are open to allow debugging as unlike with javascript they can't deoptimize compiled wasm again.

It did need to take about 300ms to serialize and deserialize a 100000 size Uint8Array.

You seemed to have an arbitrary object; if you have a Uint8Array, then that's specially known to the JS runtime so you can use it directly (this manifests itself in it being wasm_bind ABI-safe on the Rust typing side). Thus, there is a bidirectional conversion between Uint8Array the Rust type and JsValue:

  • It has a constructor that takes JsValue
  • And it implements JsCast as well.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.