Deserialize SurrealDB query with Rust

If you are new to SurrealDB and Rust you may be interested in how to get the data from a Response or even be trying to parse a ‘Value’.

The Response struct

The secret is to make a struct that will contain the keys (field names) that are present in the response. You don’t want to parse the response manually!

cargo add serde --features derive
cargo add serde_json
cargo add surrealdb
cargo add tokio --features macros,rt-multi-thread
pub async fn list_related(db: &Surreal<Db>) -> surrealdb::Result<()> {
    let mut entries = db
        .query("SELECT id, time.written as time_written FROM featured")
        .await?;
    let entries: Vec<Feature> = entries.take(0)?;
    for entry in entries {
        println!("added {:?}", entry.time_written.unwrap_or_default());
    } 
    Ok(())
}

To deconstruct this query you need a struct called Feature :

#[derive(Debug,Deserialize)]
pub struct Feature{
    id: Thing,
    time_written : Option<String>
}

To properly deserialize the query response from SurrealDB, the struct Feature must be defined to match the structure of the data being retrieved. In this case, Feature contains two fields: id and time_written. The #[derive(Debug, Deserialize)] attribute allows the Feature struct to be used for deserialization, automatically mapping the query results into Rust structs.

The function list_related demonstrates how this works. It sends a query to SurrealDB to select id and time.written (renaming it as time_written) from the featured table. The result is then deserialized into a Vec<Feature>. This allows easy access to the data fields, enabling operations like printing time_written for each entry.

By structuring the data this way, Rust can leverage type safety and structured error handling when working with database responses.