Create a GraphQL-powered project management endpoint in Rust and MongoDB - Rocket version
Tags: rust, graphql, mongodb, rocket
Published: 2022-07-25 09:14:46

---
title: Create a GraphQL-powered project management endpoint in Rust and MongoDB - Rocket version
published: true
description: This post will discuss building a project management application with Rust using the Async-graphql library and MongoDB.
tags: #Rust #GraphQL #MongoDB #Rocket
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcparr1yk5eft2kxpgtw.png
# Use a ratio of 100:42 for best results.
---
GraphQL is a query language for reading and manipulating data for APIs. It prioritizes giving clients or servers the exact data requirement by providing a flexible and intuitive syntax to describe such data. 

Compared to a traditional REST API, GraphQL provides a type system to describe schemas for data and, in turn, gives consumers of the API the affordance to explore and request the needed data using a single endpoint.

This post will discuss building a project management application with Rust using the [Async-graphql](https://github.com/async-graphql/async-graphql) library and [MongoDB](https://www.mongodb.com/). At the end of this tutorial, we will learn how to create a GraphQL endpoint that supports reading and manipulating project management data and persisting our data using MongoDB.
GitHub repository can be found [here](https://github.com/Mr-Malomz/project-mngt-rust-graphql-rocket).

# Prerequisites

To fully grasp the concepts presented in this tutorial, experience with Rust is required. Experience with MongoDB isn’t a requirement, but it’s nice to have.

We will also be needing the following:

- Basic knowledge of GraphQL
- A [MongoDB account](https://www.mongodb.com/) to host the database. [**Signup**](https://www.mongodb.com/cloud/atlas/register) **is completely free**

# Let’s code

## Getting Started

To get started, we need to navigate to the desired directory and run the command below in our terminal 

```bash
    cargo new project-mngt-rust-graphql-rocket && cd project-mngt-rust-graphql-rocket
``` 

This command creates a Rust project called  `project-mngt-rust-graphql-rocket` and navigates into the project directory.

Next, we proceed to install the required dependencies by modifying the `[dependencies]` section of the `Cargo.toml` file as shown below:
```toml
    
    //other code section goes here
    
    [dependencies]
    rocket = {version = "0.5.0-rc.2", features = ["json"]}
    async-graphql = { version = "4.0", features = ["bson", "chrono"] }
    async-graphql-rocket = "4.0.0"
    serde = "1.0.136"
    dotenv = "0.15.0"
    
    [dependencies.mongodb]
    version = "2.2.0"
    default-features = false
    features = ["sync"] 
```
`rocket = {version = "0.5.0-rc.2", features = ["json"]}` is a Rust-based framework for building web applications. It also specifies the required version and the feature type(json).

`async-graphql = { version = "4.0", features = ["bson", "chrono"] }` is a server-side library for building GraphQL in Rust. It also features `bson` and `chrono`.

`async-graphql-rocket = "4.0"` is a library that helps integrate `async-grapql` with `Rocket`.

`serde = "1.0.136"` is a framework for serializing and deserializing Rust data structures. E.g. convert Rust structs to JSON.

`dotenv = "0.15.0"` is a library for managing environment variables.

`[dependencies.mongodb]` is a driver for connecting to MongoDB. It also specifies the required version and the feature type(Sync API).

We need to run the command below to install the dependencies:
```bash
    cargo build
```

## Module system in Rust

Modules are like folder structures in our application; they simplify how we manage dependencies.

To do this, we need to navigate to the `src` folder and create the  `config`, `handler`, and `schemas` folder with their corresponding `mod.rs`  file to manage visibility.

![Updated project folder structure](https://paper-attachments.dropbox.com/s_AB562E5C2E35FE5CD8B7C6C6E910200C49A248F6538EF2E3334B4E983D325E2E_1658499586796_Screenshot+2022-07-22+at+15.19.18.png)


`config` is for modularizing configuration files.

`handler` is for modularizing GraphQL logics.

`schemas` is for modularizing GraphQL schema.

**Adding a reference to the Modules**
To use the code in the modules, we need to declare them as a module and import them into the `main.rs` file.
```rust
    //add modules
    mod config;
    mod handler;
    mod schemas;
    
    fn main() {
        println!("Hello, world!");
    }
```

## Setting up MongoDB

With that done, we need to log in or sign up into our [MongoDB](http://) account. Click the project dropdown menu and click on the **New Project** button.

![New Project](https://paper-attachments.dropbox.com/s_B58C50BB61437E91E681B5825981F54733906EC9A6070DFB4A21109C66F0E3FA_1637365380025_Screenshot+2021-11-20+at+00.33.27.png)


Enter the `projectMngt` as the project name, click **Next**, and click **Create Project..**

![enter project name](https://paper-attachments.dropbox.com/s_5DB793BEFC159F569DA013C68231051E6736BBB84507D7CF5CD2A8277968E59C_1657388688286_Screenshot+2022-07-09+at+18.44.22.png)
![Create Project](https://paper-attachments.dropbox.com/s_0E637C74C0D58C5FC3FBA1D21E2CF4F11E7592B7929DAE10790A9D12FE972D1D_1640511449329_Screenshot+2021-12-26+at+10.36.27.png)


Click on **Build a Database**

![](https://paper-attachments.dropbox.com/s_0E637C74C0D58C5FC3FBA1D21E2CF4F11E7592B7929DAE10790A9D12FE972D1D_1640511574285_Screenshot+2021-12-26+at+10.38.59.png)


Select **Shared** as the type of database.

![Shared highlighted in red](https://paper-attachments.dropbox.com/s_B58C50BB61437E91E681B5825981F54733906EC9A6070DFB4A21109C66F0E3FA_1637334670330_Screenshot+2021-11-19+at+15.59.38.png)


Click on **Create** to setup a cluster. This might take sometime to setup.

![Creating a cluster](https://paper-attachments.dropbox.com/s_B58C50BB61437E91E681B5825981F54733906EC9A6070DFB4A21109C66F0E3FA_1637334961608_Screenshot+2021-11-19+at+16.13.28.png)


Next, we need to create a user to access the database externally by inputting the **Username**, **Password** and then clicking on **Create User**. We also need to add our IP address to safely connect to the database by clicking on the **Add My Current IP Address** button. Then click on **Finish and Close** to save changes.

![Create user](https://paper-attachments.dropbox.com/s_0E637C74C0D58C5FC3FBA1D21E2CF4F11E7592B7929DAE10790A9D12FE972D1D_1640512109914_Screenshot+2021-12-26+at+10.43.36.png)
![Add IP](https://paper-attachments.dropbox.com/s_0E637C74C0D58C5FC3FBA1D21E2CF4F11E7592B7929DAE10790A9D12FE972D1D_1640512118747_Screenshot+2021-12-26+at+10.43.52.png)


On saving the changes, we should see a Database Deployments screen, as shown below:

![Database Screen](https://paper-attachments.dropbox.com/s_AB562E5C2E35FE5CD8B7C6C6E910200C49A248F6538EF2E3334B4E983D325E2E_1658506986553_Screenshot+2022-07-22+at+17.22.35.png)

## Connecting our application to MongoDB

With the configuration done, we need to connect our application with the database created. To do this, click on the **Connect** button

![Connect to database](https://paper-attachments.dropbox.com/s_AB562E5C2E35FE5CD8B7C6C6E910200C49A248F6538EF2E3334B4E983D325E2E_1658507076696_Screenshot+2022-07-22+at+17.22.35.png)


Click on **Connect your application**, change the **Driver** to `Rust` and the **Version** as shown below. Then click on the copy **icon** to copy the connection string.

![connect application](https://paper-attachments.dropbox.com/s_0E637C74C0D58C5FC3FBA1D21E2CF4F11E7592B7929DAE10790A9D12FE972D1D_1640513302462_Screenshot+2021-12-26+at+11.03.40.png)
![Copy connection string](https://paper-attachments.dropbox.com/s_AB562E5C2E35FE5CD8B7C6C6E910200C49A248F6538EF2E3334B4E983D325E2E_1658507174205_Screenshot+2022-07-22+at+17.22.53.png)


**Setup Environment Variable**
Next, we must modify the copied connection string with the user's password we created earlier and change the database name. To do this, first, we need to create a `.env` file in the root directory, and in this file, add the snippet below:
```bash

    MONGOURI=mongodb+srv://<YOUR USERNAME HERE>:<YOUR PASSWORD HERE>@cluster0.e5akf.mongodb.net/<DATABASE NAME>?retryWrites=true&w=majority
```
Sample of a properly filled connection string below:
```bash
    MONGOURI=mongodb+srv://malomz:malomzPassword@cluster0.e5ahghkf.mongodb.net/projectMngt?retryWrites=true&w=majority
```

## Creating GraphQL Endpoints

With the setup done, we need to create a schema to represent our application data. To do this, we need to navigate to the `schemas` folder, and in this folder, create a `project_schema.rs` file and add the snippet below:
```rust
    use async_graphql::{Enum, InputObject, SimpleObject};
    use mongodb::bson::oid::ObjectId;
    use serde::{Deserialize, Serialize};
    
    //owner schema
    #[derive(Debug, Clone, Serialize, Deserialize, SimpleObject)]
    pub struct Owner {
        #[serde(skip_serializing_if = "Option::is_none")]
        pub _id: Option<ObjectId>,
        pub name: String,
        pub email: String,
        pub phone: String,
    }
    
    #[derive(InputObject)]
    pub struct CreateOwner {
        pub name: String,
        pub email: String,
        pub phone: String,
    }
    
    #[derive(InputObject)]
    pub struct FetchOwner {
        pub _id: String,
    }
    
    //project schema
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Enum)]
    pub enum Status {
        NotStarted,
        InProgress,
        Completed,
    }
    
    #[derive(Debug, Clone, Serialize, Deserialize, SimpleObject)]
    pub struct Project {
        #[serde(skip_serializing_if = "Option::is_none")]
        pub _id: Option<ObjectId>,
        pub owner_id: String,
        pub name: String,
        pub description: String,
        pub status: Status,
    }
    
    #[derive(InputObject)]
    pub struct CreateProject {
        pub owner_id: String,
        pub name: String,
        pub description: String,
        pub status: Status,
    }
    
    #[derive(InputObject)]
    pub struct FetchProject {
        pub _id: String,
    }
```
The snippet above does the following:

- Imports required dependencies
- Uses the `derive` macro to generate implementation support for `Owner`, `CreateOwner`, `FetchOwner`, `Status`, `Project`, `CreateProject`, and `FetchProject`. The snippet also uses the procedural macro from the `serde` and `async-graphql` library to  serialize/deserialize and convert Rust structs to a GraphQL schema.

Next, we must register the `project_schema.rs` file as part of the `schemas` module. To do this, open the `mod.rs` in the `schemas` folder and add the snippet below:
```rust
    pub mod project_schema;
```
**Database Logic**
With the schema fully set up and made available to be consumed, we can now create our database logic that will do the following:

- Create project owner
- Get all owners
- Get a single owner
- Create project
- Get all projects
- Get a single project

To do this, First, we need to navigate to the `config` folder, and in this folder, create a `mongo.rs` file and add the snippet below:
```rust
    use dotenv::dotenv;
    use std::{env, io::Error};
    use mongodb::{
        bson::{doc, oid::ObjectId},
        sync::{Client, Collection, Database},
    };
    use crate::schemas::project_schema::{Owner, Project};
    
    pub struct DBMongo {
        db: Database,
    }
    
    impl DBMongo {
        pub fn init() -> Self {
            dotenv().ok();
            let uri = match env::var("MONGOURI") {
                Ok(v) => v.to_string(),
                Err(_) => format!("Error loading env variable"),
            };
            let client = Client::with_uri_str(uri).unwrap();
            let db = client.database("projectMngt");
            DBMongo { db }
        }
    
        fn col_helper<T>(data_source: &Self, collection_name: &str) -> Collection<T> {
            data_source.db.collection(collection_name)
        }
    }
```
The snippet above does the following:

- Imports the required dependencies
- Creates a `DBMongo` struct with a `db` field to access MongoDB database
- Creates an implementation block that adds methods to the `DBMongo` struct
- Adds an `init` method to the implementation block to load the environment variable, creates a connection to the database, and returns an instance of the `DBMongo` struct
- Adds a `col_helper` method; a helper function to create MongoDB collection

Next, we need to add the remaining methods to the `DBMongo` implementation to cater to the project management operations:
```rust
    //imports goes here
    
    pub struct DBMongo {
        db: Database,
    }
    
    impl DBMongo {
        pub fn init() -> Self {
            //init code goes here
        }
    
        fn col_helper<T>(data_source: &Self, collection_name: &str) -> Collection<T> {
            data_source.db.collection(collection_name)
        }
    
        //Owners logic
        pub fn create_owner(&self, new_owner: Owner) -> Result<Owner, Error> {
            let new_doc = Owner {
                _id: None,
                name: new_owner.name.clone(),
                email: new_owner.email.clone(),
                phone: new_owner.phone.clone(),
            };
            let col = DBMongo::col_helper::<Owner>(&self, "owner");
            let data = col
                .insert_one(new_doc, None)
                .ok()
                .expect("Error creating owner");
            let new_owner = Owner {
                _id: data.inserted_id.as_object_id(),
                name: new_owner.name.clone(),
                email: new_owner.email.clone(),
                phone: new_owner.phone.clone(),
            };
            Ok(new_owner)
        }
    
        pub fn get_owners(&self) -> Result<Vec<Owner>, Error> {
            let col = DBMongo::col_helper::<Owner>(&self, "owner");
            let cursors = col
                .find(None, None)
                .ok()
                .expect("Error getting list of owners");
            let owners: Vec<Owner> = cursors.map(|doc| doc.unwrap()).collect();
            Ok(owners)
        }
    
        pub fn single_owner(&self, id: &String) -> Result<Owner, Error> {
            let obj_id = ObjectId::parse_str(id).unwrap();
            let filter = doc! {"_id": obj_id};
            let col = DBMongo::col_helper::<Owner>(&self, "owner");
            let owner_detail = col
                .find_one(filter, None)
                .ok()
                .expect("Error getting owner's detail");
            Ok(owner_detail.unwrap())
        }
    
        //project logics
        pub fn create_project(&self, new_project: Project) -> Result<Project, Error> {
            let new_doc = Project {
                _id: None,
                owner_id: new_project.owner_id.clone(),
                name: new_project.name.clone(),
                description: new_project.description.clone(),
                status: new_project.status.clone(),
            };
            let col = DBMongo::col_helper::<Project>(&self, "project");
            let data = col
                .insert_one(new_doc, None)
                .ok()
                .expect("Error creating project");
            let new_project = Project {
                _id: data.inserted_id.as_object_id(),
                owner_id: new_project.owner_id.clone(),
                name: new_project.name.clone(),
                description: new_project.description.clone(),
                status: new_project.status.clone(),
            };
            Ok(new_project)
        }
    
        pub fn get_projects(&self) -> Result<Vec<Project>, Error> {
            let col = DBMongo::col_helper::<Project>(&self, "project");
            let cursors = col
                .find(None, None)
                .ok()
                .expect("Error getting list of projects");
            let projects: Vec<Project> = cursors.map(|doc| doc.unwrap()).collect();
            Ok(projects)
        }
    
        pub fn single_project(&self, id: &String) -> Result<Project, Error> {
            let obj_id = ObjectId::parse_str(id).unwrap();
            let filter = doc! {"_id": obj_id};
            let col = DBMongo::col_helper::<Project>(&self, "project");
            let project_detail = col
                .find_one(filter, None)
                .ok()
                .expect("Error getting project's detail");
            Ok(project_detail.unwrap())
        }
    }
```
The snippet above does the following:

- Adds a `create_owner` method that takes in a `self` and `new_owner` as parameters and returns the created owner or an error. Inside the method, we created a new document using the `Owner` struct. Then we use the `col_helper` method to create a new collection and access the `insert_one` function to create a new owner and handle errors. Finally, we returned the created owner information
- Adds a `get_owners` method that takes in a `self` as parameters and returns the list of owners or an error. Inside the method,  we use the `col_helper` method to create a new collection and access the `find` function without any filter so that it can match all the documents inside the database and returned the list optimally using the `map()` method to loop through the list of owners, and handle errors
- Adds a `single_owner` method that takes in a `self` and `id` as parameters and returns the owner detail or an error. Inside the method, we converted the `id` to an `ObjectId`  and used it as a filter to get the matching document. Then we use the `col_helper` method to create a new collection and access the `find_one` function from the collection to get the details of the owner and handle errors
- Adds a `create_project` method that takes in a `self` and `new_project` as parameters and returns the created project or an error. Inside the method, we created a new document using the `Project` struct. Then we use the `col_helper` method to create a new collection and access the `insert_one` function to create a new project and handle errors. Finally, we returned the created project information
- Adds a `get_projects` method that takes in a `self` as parameters and returns the list of projects or an error. Inside the method,  we use the `col_helper` method to create a new collection and access the `find` function without any filter so that it can match all the documents inside the database and returned the list optimally using the `map()` method to loop through the list of projects, and handle errors
- Adds a `single_project` method that takes in a `self` and `id` as parameters and returns the project detail or an error. Inside the method, we converted the `id` to an `ObjectId`  and used it as a filter to get the matching document. Then we use the `col_helper` method to create a new collection and access the `find_one` function from the collection to get the details of the project and handle errors

Finally, we must register the `mongo.rs` file as part of the `config` module. To do this, open the `mod.rs` in the `config` folder and add the snippet below:
```rust
    pub mod mongo;
```
**GraphQL Handlers**
With the database logic sorted out, we can start using them to create our GraphQL handlers. To do this, First, we need to navigate to the `handler` folder, and in this folder, create a `graphql_handler.rs` file and add the snippet below:
```rust
    use crate::{
        config::mongo::DBMongo,
        schemas::project_schema::{
            CreateOwner, CreateProject, FetchOwner, FetchProject, Owner, Project,
        },
    };
    use async_graphql::{Context, EmptySubscription, FieldResult, Object, Schema};
    
    pub struct Query;
    
    #[Object(extends)]
    impl Query {
        //owners query
        async fn owner(&self, ctx: &Context<'_>, input: FetchOwner) -> FieldResult<Owner> {
            let db = &ctx.data_unchecked::<DBMongo>();
            let owner = db.single_owner(&input._id).unwrap();
            Ok(owner)
        }
    
        async fn get_owners(&self, ctx: &Context<'_>) -> FieldResult<Vec<Owner>> {
            let db = &ctx.data_unchecked::<DBMongo>();
            let owners = db.get_owners().unwrap();
            Ok(owners)
        }
    
        //projects query
        async fn project(&self, ctx: &Context<'_>, input: FetchProject) -> FieldResult<Project> {
            let db = &ctx.data_unchecked::<DBMongo>();
            let project = db.single_project(&input._id).unwrap();
            Ok(project)
        }
    
        async fn get_projects(&self, ctx: &Context<'_>) -> FieldResult<Vec<Project>> {
            let db = &ctx.data_unchecked::<DBMongo>();
            let projects = db.get_projects().unwrap();
            Ok(projects)
        }
    }
    
    pub struct Mutation;
    
    #[Object]
    impl Mutation {
        //owner mutation
        async fn create_owner(&self, ctx: &Context<'_>, input: CreateOwner) -> FieldResult<Owner> {
            let db = &ctx.data_unchecked::<DBMongo>();
            let new_owner = Owner {
                _id: None,
                email: input.email,
                name: input.name,
                phone: input.phone,
            };
            let owner = db.create_owner(new_owner).unwrap();
            Ok(owner)
        }
    
        async fn create_project(
            &self,
            ctx: &Context<'_>,
            input: CreateProject,
        ) -> FieldResult<Project> {
            let db = &ctx.data_unchecked::<DBMongo>();
            let new_project = Project {
                _id: None,
                owner_id: input.owner_id,
                name: input.name,
                description: input.description,
                status: input.status,
            };
            let project = db.create_project(new_project).unwrap();
            Ok(project)
        }
    }
    
    pub type ProjectSchema = Schema<Query, Mutation, EmptySubscription>;
```
The snippet above does the following:

- Imports the required dependencies
- Creates a `Query` struct with implementation methods related to querying the database using the corresponding methods from the database logic
- Creates a `Mutation` struct with implementation methods related to modifying the database using the corresponding methods from the database logic.
- Creates a `ProjectSchema` type to construct how our GraphQL is using the `Query` struct, `Mutation` struct, and `EmptySubscription` since we don’t have any subscriptions.


**Creating GraphQL Server**
Finally, we can start creating our GraphQL server by integrating the `ProjectSchema` and MongoDB with Actix web. To do this, we need to navigate to the `main.rs` file and modify it as shown below:
```rust

    mod config;
    mod handler;
    mod schemas;
    
    //add
    use async_graphql::{
        http::{playground_source, GraphQLPlaygroundConfig},
        EmptySubscription, Schema,
    };
    use async_graphql_rocket::{GraphQLQuery, GraphQLRequest, GraphQLResponse};
    use config::mongo::DBMongo;
    use handler::graphql_handler::{Mutation, ProjectSchema, Query};
    use rocket::{response::content, routes, State};
    
    #[rocket::get("/graphql?<query..>")]
    async fn graphql_query(schema: &State<ProjectSchema>, query: GraphQLQuery) -> GraphQLResponse {
        query.execute(schema).await
    }
    
    #[rocket::post("/graphql", data = "<request>", format = "application/json")]
    async fn graphql_mutation(
        schema: &State<ProjectSchema>,
        request: GraphQLRequest,
    ) -> GraphQLResponse {
        request.execute(schema).await
    }
    
    #[rocket::get("/")]
    async fn graphql_playground() -> content::RawHtml<String> {
        content::RawHtml(playground_source(GraphQLPlaygroundConfig::new("/graphql")))
    }
    
    #[rocket::launch]
    fn rocket() -> _ {
        let db = DBMongo::init();
        let schema = Schema::build(Query, Mutation, EmptySubscription)
            .data(db)
            .finish();
        rocket::build().manage(schema).mount(
            "/",
            routes![graphql_query, graphql_mutation, graphql_playground],
        )
    }
```
The snippet above does the following:

- Imports the required dependencies
- Creates a `graphql_query` function with `get` procedural macro to specify the GraphQL route and uses the `ProjectSchema` type to execute methods related to querying the database
- Creates a `graphql_mutation` function with `post` procedural macro to specify the GraphQL route and uses the `ProjectSchema` type to execute methods related to modifying the database
- Creates a `graphql_playground` function to create **GraphiQL**; a GraphQL playground we can access from a browser
- Uses the `#[rocket::launch]` macro to run the `rocket` function that generates an application entry point and runs the server. The `rocket` also function does the following:
    - Creates a `db` variable to establish a connection to MongoDB by calling the `init()` method and uses it to build a GraphQL data
    - Builds the application using the `build` function, adds the `schema` to state, and configures the route to include the `graphql_query`, `graphql_mutation`, and `graphql_playground`

With that done, we can test our application by running the command below in our terminal.
```bash
    cargo run
```
Then navigate to `http://127.0.0.1:8000` on a web browser.


![Create project](https://paper-attachments.dropbox.com/s_AB562E5C2E35FE5CD8B7C6C6E910200C49A248F6538EF2E3334B4E983D325E2E_1658529338277_Screenshot+2022-07-22+at+23.34.36.png)
![Get list of project](https://paper-attachments.dropbox.com/s_AB562E5C2E35FE5CD8B7C6C6E910200C49A248F6538EF2E3334B4E983D325E2E_1658529303179_Screenshot+2022-07-21+at+21.53.31.png)

![Get single owner](https://paper-attachments.dropbox.com/s_AB562E5C2E35FE5CD8B7C6C6E910200C49A248F6538EF2E3334B4E983D325E2E_1658529338231_Screenshot+2022-07-22+at+23.32.34.png)
![Create Owner](https://paper-attachments.dropbox.com/s_AB562E5C2E35FE5CD8B7C6C6E910200C49A248F6538EF2E3334B4E983D325E2E_1658529303204_Screenshot+2022-07-22+at+23.31.10.png)



![Database with data](https://paper-attachments.dropbox.com/s_AB562E5C2E35FE5CD8B7C6C6E910200C49A248F6538EF2E3334B4E983D325E2E_1658529546852_Screenshot+2022-07-22+at+08.54.40.png)

# Conclusion

This post discussed how to modularize a Rust application, build a GraphQL server, and persist our data using MongoDB.

These resources might be helpful:

- [Async-GraphQL](https://github.com/async-graphql/async-graphql)
- [Rocket](https://rocket.rs/)
- [MongoDB Rust Driver](https://github.com/mongodb/mongo-rust-driver)
- [Build a REST API with Rust and MongoDB](https://dev.to/hackmamba/build-a-rest-api-with-rust-and-mongodb-rocket-version-ah5)
- [Async-GraphQL Rocket integration](https://github.com/async-graphql/async-graphql/tree/master/integrations/rocket)
- [Serde (Serializing and Deserializing library)](https://serde.rs/)