如何使用Serde序列化带有顶级键的结构体?

3

我目前正在使用Rocket开发一个Web API,该API使用以下结构体来处理错误响应:

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

实际上,序列化此结构会产生类似于以下JSON的JSON:

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

我希望以这种方式序列化它:
{
  "error": {
    "code": 400,
    "reason": "Bad Request"
  }
}

不使用两个不同结构,最简单的方法是什么?

提前感谢您的帮助!


1
除非您为其实现自己的序列化/反序列化,否则我不确定它是否可能。 - Netwave
1个回答

1
我能想到的最简单的方法是将你的结构体包装在一个只有一个结构体变量的enum中:
#[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>,
    }
}

这件令人烦恼的事情是类型和构造函数现在必须有不同的名称。例如,如果一个函数需要一个ErrorResponse,现在它必须使用ErrorResponseWrapper(虽然你可能需要想出一个更好的名称),但你必须使用ErrorResponseWrapper::ErrorResponse变量来构建这样的值。幸运的是,你可以至少在导入中添加use ErrorResponseWrapper::ErrorResponse;

Playground


很好,他可能只需要重新导出错误响应,就可以了。 - Netwave
好主意,我没有想到把它转换成枚举。谢谢你的快速回答! - baptiste0928

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接