gpt4 book ai didi

rust - 如何在自定义结构序列化程序中嵌套字段?

转载 作者:行者123 更新时间:2023-12-03 11:27:02 26 4
gpt4 key购买 nike

给定以下 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>,
}

如何在序列化过程中将一些字段分组到命名空间(嵌套它们)?例如,将 titlemessagetrace 字段分组到 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 的 frominto进行最终转换。

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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com