How to serialize a struct with a top-level key with Serde?

Viewed 244

I'm currenlty developping a web API with Rocket that use the following struct for error responses :

#[derive(Serialize, Deserialize)]
pub struct ErrorResponse {
    code: u16,
    reason: &'static str,
    #[serde(skip_serializing_if = "Option::is_none")]
    description: Option<String>,
}

Actually, serializing this struct produce json similar to this :

{
  "code": 400,
  "reason": "Bad Request"
}

I'm looking to serialize it this way:

{
  "error": {
    "code": 400,
    "reason": "Bad Request"
  }
}

What is the easiest way to do that without using two different sructs ?

Thank you in advance for your help!

1 Answers

The simplest way I can think of is to wrap your struct in an enum with a single struct variant:

#[derive(Serialize, Deserialize)]
pub enum ErrorResponseWrapper {
    #[serde(rename = "error")]
    ErrorResponse {
        code: u16,
        reason: &'static str,
        #[serde(skip_serializing_if = "Option::is_none")]
        description: Option<String>,
    }
}

The annoying thing about this is that the type and the constructor must have different names now. I.e. if a function takes an ErrorResponse it now has to take an ErrorResponseWrapper (although you probably wanna come up with a better name than that), but you have to construct such a value with the ErrorResponseWrapper::ErrorResponse variant. Fortunately you can at least add use ErrorResponseWrapper::ErrorResponse; to your imports.

Playground

Related