Search code examples
rustmutableactix-web

Convert web::Json<T> to &mut T


I am trying to write a simple api to create user in actix-web but I need to pass the User object as mutable reference in the method db_connector.create_user() because it needs to be edited behind the scenes - in order to add id, creation-date etc.

#[post("/users")]
pub async fn create_user(
    db_connector: web::Data<DBConnector>,
    user: web::Json<User>,
) -> impl Responder {
    match db_connector.create_user(&user.into_inner()).await {
        Ok(_) => HttpResponse::Created().finish(),
        Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
    }
}

But I am not sure how to convert web::Json<User> to &mut User. Thanks in advance for the help.


Solution

  • #[post("/users")]
    pub async fn create_user(
        db_connector: web::Data<DBConnector>,
        web::Json(mut user): web::Json<User>,
    ) -> impl Responder {
        match db_connector.create_user(&mut user).await {
            Ok(_) => HttpResponse::Created().finish(),
            Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
        }
    }
    

    should work fine, though I didn't test it (and don't know actix).

    According to the documentation Json is

    pub struct Json<T>(pub T)
    

    so it's a trivial wrapper you can pattern match on, and you just need to have a mutable binding in order to create a mutable reference from it.

    Alternatively if you want to keep the existing binding style for some reason,

    #[post("/users")]
    pub async fn create_user(
        db_connector: web::Data<DBConnector>,
        mut user: web::Json<User>,
    ) -> impl Responder {
        match db_connector.create_user(&mut user.0).await {
            Ok(_) => HttpResponse::Created().finish(),
            Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
        }
    }
    

    same deal, just without the pattern-based deconstruction of the input Json.

    Hell, even just

    #[post("/users")]
    pub async fn create_user(
        db_connector: web::Data<DBConnector>,
        user: web::Json<User>,
    ) -> impl Responder {
        match db_connector.create_user(&mut user.into_inner()).await {
            Ok(_) => HttpResponse::Created().finish(),
            Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
        }
    }
    

    probably works.