1

I have a small tauri app that on the JS part sends some data back to the rust backend using the invoke method.

The method works, most of the data arrives to the backend. The data itself contains a map, which does not arrive though.

const [details, setDetails] = useState({
    name: "",
    country: "",
    address: "",
    items: new Map<String, number>
})
...
async function handleSubmit(e: any) {
    e.preventDefault()
    console.log(details)
    await invoke('submit_new_customer', { details }).then((submitted) => { ... })
}

The logged out details:

{
    name: "Alfred Gustavsson",
    country: "Norway",
    address: "Exapmle street",
    items: Map(1) {'3' => 1}
}

The backend:

#[derive(Serialize, Deserialize, Debug)]
struct NewCustomerInput {
    name: String,
    country: String,
    address: Option<String>,
    items: HashMap<String, usize>
}

#[tauri::command]
fn submit_new_customer(details: NewCustomerInput) -> bool {
    println!("{:?}", details);
    ...

From the print I can see that the items is {}. How can I setup my struct to accept the Map from the fronted?

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • Please show us some JS code which sends the (constant) NewCustomerInput that you described. Alternatively, show us some wireshark or webserver logging which reveals exactly how `items` got serialized when it went out on the wire. – J_H Sep 01 '23 at 03:48
  • 4
    Maps have no built-in serialization. Check out https://stackoverflow.com/questions/29085197/how-do-you-json-stringify-an-es6-map – ray Sep 01 '23 at 04:05
  • @J_H it is a tauri app, it never goes out to the network. I added some JS code. – András Krausz Sep 01 '23 at 17:25
  • @ray Thanks a lot, I just changed it to an object and now it works. – András Krausz Sep 01 '23 at 18:02

1 Answers1

3

As mentioned in the comments, you will need to convert your Map into an Object, prior to sending:

const mapToObj = (map) => Object.fromEntries([...map.entries()]);

const objToMap = (obj) => new Map(Object.entries(obj));

const serializableDetails = (details) => {
    const { name, address, country, items } = details;
    return { name, address, country, items: mapToObj(items) }
}

const jsDetails = {
    name: 'Joe Biden',
    address: '1600 Pennsylvania Ave NW, Washington, DC 20500',
    country: 'USA',
    items: objToMap({ foo: 1, bar: 2 }) 
}

console.log(jsDetails); // Note: the Map will not show in the snippet console

const postDetails = serializableDetails(jsDetails);

console.log(postDetails);
.as-console-wrapper { top: 0; max-height: 100% !important; }

Usage

async function handleSubmit(e: any) {
    e.preventDefault()
    await invoke('submit_new_customer', {
        details: serializableDetails(details); // pre-process here
    })
        .then((submitted) => { ... })
}
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132