# Serializing and Deserializing Arbitrary Data Into and From `JsValue` with Serde

It's possible to pass arbirtrary data from Rust to JavaScript by serializing it
with [Serde](https://github.com/serde-rs/serde). `wasm-bindgen` includes the
`JsValue` type, which streamlines serializing and deserializing.

## Enable the `"serde-serialize"` Feature

To enable the `"serde-serialize"` feature, do two things in `Cargo.toml`:

1. Add the `serde` and `serde_derive` crates to `[dependencies]`.
2. Add `features = ["serde-serialize"]` to the existing `wasm-bindgen`
   dependency.

```toml
[dependencies]
serde = "^1.0.59"
serde_derive = "^1.0.59"

[dependencies.wasm-bindgen]
version = "^0.2"
features = ["serde-serialize"]
```

## Import Serde's Custom-Derive Macros

In your top-level Rust file (e.g. `lib.rs` or `main.rs`), enable the `Serialize`
and `Deserialize` custom-derive macros:

```rust
#[macro_use]
extern crate serde_derive;
```

## Derive the `Serialize` and `Deserialize` Traits

Add `#![derive(Serialize, Deserialize)]` to your type. All of your type's
members must also be supported by Serde, i.e. their types must also implement
the `Serialize` and `Deserialize` traits.

For example, let's say we'd like to pass this `struct` to JavaScript; doing so
is not possible in `wasm-bindgen` normally due to the use of `HashMap`s, arrays,
and nested `Vec`s. None of those types are supported for sending across the wasm
ABI naively, but all of them implement Serde's `Serialize` and `Deserialize`.

Note that we do not need to use the `#[wasm_bindgen]` macro.

```rust
#[derive(Serialize)]
pub struct Example {
    pub field1: HashMap<u32, String>,
    pub field2: Vec<Vec<f32>>,
    pub field3: [f32; 4],
}
```

## Send it to JavaScript with `JsValue::from_serde`

Here's a function that will pass an `Example` to JavaScript by serializing it to
`JsValue`:

```rust
#[wasm_bindgen]
pub fn send_example_to_js() -> JsValue {
    let mut field1 = HashMap::new();
    field1.insert(0, String::from("ex"));
    let example = Example {
        field1,
        field2: vec![vec![1., 2.], vec![3., 4.]],
        field3: [1., 2., 3., 4.]
    };

    JsValue::from_serde(&example).unwrap()
}
```

## Receive it from JavaScript with `JsValue::into_serde`

Here's a function that will receive a `JsValue` parameter from JavaScript and
then deserialize an `Example` from it:

```rust
#[wasm_bindgen]
pub fn receive_example_from_js(val: &JsValue) {
    let example: Example = val.into_serde().unwrap();
    ...
}
```

## JavaScript Usage

In the `JsValue` that JavaScript gets, `field1` will be an `Object` (not a
JavaScript `Map`), `field2` will be a JavaScript `Array` whose members are
`Array`s of numbers, and `field3` will be an `Array` of numbers.

```js
import { send_example_to_js, receive_example_from_js } from "example";

// Get the example object from wasm.
let example = send_example_to_js();

// Add another "Vec" element to the end of the "Vec<Vec<f32>>"
example.field2.push([5,6]);

// Send the example object back to wasm.
receive_example_from_js(example);
```
