作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
给定以下 struct
定义。
#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub (in crate) struct ResponseError {
pub status: StatusCode,
pub title: String,
pub message: String,
pub trace: Option<String>,
}
如何在序列化过程中将一些字段分组到命名空间(嵌套它们)?例如,将 title
、message
和 trace
字段分组到 error
命名空间中,如下所示。
{
"status": 0,
"error": {
"title": "",
"message": "",
"trace": "",
},
}
目标是能够在输出结构化响应的同时在 Rust 中创建一个扁平的 struct
。这是我能想到的方法。
impl Serialize for ResponseError {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("Color", if self.trace.is_some() { 4 } else { 3 })?;
state.serialize_field("status", &self.status)?;
state.serialize_field("error.title", &self.title)?;
state.serialize_field("error.message", &self.message)?;
if let Some(trace) = self.trace {
state.serialize_field("error.trace", &self.trace)?;
};
state.end()
}
}
最佳答案
解决这个问题的一种方法是为您的“有线格式”定义单独的结构,然后提供 From<>
的实现。与有线格式相互转换,最后使用 serde 的 from
和 into
进行最终转换。
wire 结构的实现和 From 的实现有点乏味 - 但很简单:
use serde::{Serialize,Deserialize};
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(from = "ResponseErrorWireFormat", into = "ResponseErrorWireFormat")]
pub struct ResponseError {
pub status: String,
pub title: String,
pub message: String,
pub trace: Option<String>,
}
#[derive(Serialize, Deserialize)]
pub struct ResponseErrorInfoWireFormat {
pub title: String,
pub message: String,
pub trace: Option<String>,
}
#[derive(Serialize, Deserialize)]
pub struct ResponseErrorWireFormat {
pub status: String,
pub info: ResponseErrorInfoWireFormat
}
impl From<ResponseErrorWireFormat> for ResponseError {
fn from(v: ResponseErrorWireFormat) -> ResponseError {
ResponseError {
status: v.status,
title: v.info.title,
message: v.info.message,
trace: v.info.trace,
}
}
}
impl From<ResponseError> for ResponseErrorWireFormat {
fn from(v: ResponseError) -> ResponseErrorWireFormat {
ResponseErrorWireFormat {
status: v.status,
info: ResponseErrorInfoWireFormat {
title: v.title,
message: v.message,
trace: v.trace,
}
}
}
}
那么使用它的代码就很简单了:
fn main() {
let v = ResponseError {
status: "an error".to_string(),
title: "an error title".to_string(),
message: "oh my, an error!".to_string(),
trace: Some("it happened right here.".to_string()),
};
let serialized = serde_json::to_string(&v).unwrap();
println!("serialized = {}", serialized);
let deserialized: ResponseError = serde_json::from_str(&serialized).unwrap();
println!("deserialized = {:?}", deserialized);
}
可以找到完整的例子here
关于rust - 如何在自定义结构序列化程序中嵌套字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62033506/
我是一名优秀的程序员,十分优秀!