Newbie Rust Rocket

Hi everyone!
I'm a very newbie on Rust and rocket. I wonder how handle JSON validation. I see the guard Json but how return a 4xx json response with serde error?
Thanks

You will want to post some more details and code of what you want for more detailed help, but let's say your return type on success is some type I will denote by S. Then you can change the return type to e.g. Result<S, BadRequest<Json>> to return either an Ok(successful_value_here) or an Err(BadRequest(Json(object_to_convert_to_json))) to show the error.

The BadRequest part is a wrapper you can put around a response, which responds with the wrapped item and sets the response code to 400 Bad Request. If you wish to return multiple different response codes in different situations, you can use the Custom wrapper instead, which allows you to pass the status code as an argument instead of letting it be part of the type.

The Json thing in the type above is a wrapper around any object that will serialize the object to json and respond with it (and set the content type). When using this tool, serialization is done using the crate serde. Note that this is not the same as the content::Json type, which is more like BadRequest and just accepts a string and sets the content type, while the one from rocket_contrib will also perform the conversion to json for you.

Note that all of this is for the situation where the json you received was valid json, but the values in the json is bad in some way.

1 Like

Hi Alice!

Thanks for your answer.

I started with this code:

But I got an internal server error

Error: Response was a non-`Responder` `Err`: BadRequest(Some(Json(ErrorMessage { message: "invalid type: integer `1`, expected a string at line 1 column 11" })))

@j3ans please do not share code as images, but as plain text instead.
Stackoverflow has a neat entry about this.

There are quite a lot of types missing in your image such as Hello and MyError

Sorry for the picture. Here, the code:

#[derive(Debug, Serialize, Deserialize, Validate)]
struct Hello {
    #[validate(length(min = 5, max = 20))]
    name: String,
}

#[derive(Debug)]
enum MyError {
    BadPayload(String)
}

#[derive(Debug, Deserialize)]
struct ErrorMessage {
    message: String,
}

impl FromDataSimple for Hello {
    type Error = MyError;
    fn from_data(req: &Request, data: Data) -> data::Outcome<Self, MyError> {
        let hello: serde_json::Result<Hello> = serde_json::from_reader(data.open());
        match hello {
            Ok(h) => data::Outcome::Success(h),
            Err(e) => {
                data::Outcome::Failure((Status::UnprocessableEntity, MyError::BadPayload(e.to_string())))
            }
        }
    }
}

#[post("/hello", data = "<hello>")]
fn index(hello: Result<Hello, MyError>) -> Result<Json<Hello>, response::status::BadRequest<Json<ErrorMessage>>> {
   match hello {
       Ok(h) => Ok(Json(h)),
       Err(error) => {
            match error {
                MyError::BadPayload(s) => Err(response::status::BadRequest(Some(Json(ErrorMessage {message: s.to_string() }))))
            }
       }
   } 
}

Ok so I found my mistake. Missing Serialize derive on ErrorMessage.

What was the error message?

The error message was : Error: Response was a non-Responder

How did it even compile in the first place if that was the mistake?

I don't know