枚举类型的自定义 serde 序列化
Custom serde serialization for enum type
我有以下数据结构,它应该能够保存字符串、u64 值、布尔值或字符串向量。
#[derive(Serialize, Deserialize)]
pub enum JsonRpcParam {
String(String),
Int(u64),
Bool(bool),
Vec(Vec<String>)
}
这个数据结构的用例是构建 JSON 可以有多种类型的 RPC 参数,所以我可以构建一个像这样的参数列表:
let mut params : Vec<JsonRpcParam> = Vec::new();
params.push(JsonRpcParam::String("Test".to_string()));
params.push(JsonRpcParam::Bool(true));
params.push(JsonRpcParam::Int(64));
params.push(JsonRpcParam::Vec(vec![String::from("abc"), String::from("cde")]));
我现在的问题是序列化。我在序列化部分使用 serde_json 。上面发布的向量的默认序列化产生:
[
{
"String":"Test"
},
{
"Bool":true
},
{
"Int":64
},
{
"Vec":[
"abc",
"cde"
]
}
]
相反,我希望序列化看起来像这样:
[
"Test",
true,
64,
["abc","cde"]
]
我试图为此类型实现自定义序列化方法,但不知道如何实现我想要的,我的尝试如下所示:
impl Serialize for JsonRpcParam {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer {
match *self {
JsonRpcParam::String(x) => serializer.serialize_str(x),
JsonRpcParam::Int(x) => serializer.serialize_u64(x),
JsonRpcParam::Bool(x) => serializer.serialize_bool(x),
JsonRpcParam::Vec(x) => _
}
}
}
而不是手动实施 Serialize
you can instead use #[serde(untagged)]
。
在你的情况下,这将非常有效。但是,请注意,如果枚举变体不是唯一的并且无法从 JSON 中清楚地识别出来,那么它将反序列化为第一个匹配的变体。简而言之,如果你也有例如随后的 JsonRpcParam::OtherString(String)
,然后将反序列化为 JsonRpcParam::String(String)
.
#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
pub enum JsonRpcParam {
String(String),
Int(u64),
Bool(bool),
Vec(Vec<String>),
}
如果您现在使用例如serde_json::to_string_pretty()
,然后它将以您想要的格式产生输出:
fn main() {
let mut params: Vec<JsonRpcParam> = Vec::new();
params.push(JsonRpcParam::String("Test".to_string()));
params.push(JsonRpcParam::Bool(true));
params.push(JsonRpcParam::Int(64));
params.push(JsonRpcParam::Vec(vec![
String::from("abc"),
String::from("cde"),
]));
let json = serde_json::to_string_pretty(¶ms).unwrap();
println!("{}", json);
}
输出:
[
"Test",
true,
64,
[
"abc",
"cde"
]
]
我有以下数据结构,它应该能够保存字符串、u64 值、布尔值或字符串向量。
#[derive(Serialize, Deserialize)]
pub enum JsonRpcParam {
String(String),
Int(u64),
Bool(bool),
Vec(Vec<String>)
}
这个数据结构的用例是构建 JSON 可以有多种类型的 RPC 参数,所以我可以构建一个像这样的参数列表:
let mut params : Vec<JsonRpcParam> = Vec::new();
params.push(JsonRpcParam::String("Test".to_string()));
params.push(JsonRpcParam::Bool(true));
params.push(JsonRpcParam::Int(64));
params.push(JsonRpcParam::Vec(vec![String::from("abc"), String::from("cde")]));
我现在的问题是序列化。我在序列化部分使用 serde_json 。上面发布的向量的默认序列化产生:
[
{
"String":"Test"
},
{
"Bool":true
},
{
"Int":64
},
{
"Vec":[
"abc",
"cde"
]
}
]
相反,我希望序列化看起来像这样:
[
"Test",
true,
64,
["abc","cde"]
]
我试图为此类型实现自定义序列化方法,但不知道如何实现我想要的,我的尝试如下所示:
impl Serialize for JsonRpcParam {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer {
match *self {
JsonRpcParam::String(x) => serializer.serialize_str(x),
JsonRpcParam::Int(x) => serializer.serialize_u64(x),
JsonRpcParam::Bool(x) => serializer.serialize_bool(x),
JsonRpcParam::Vec(x) => _
}
}
}
而不是手动实施 Serialize
you can instead use #[serde(untagged)]
。
在你的情况下,这将非常有效。但是,请注意,如果枚举变体不是唯一的并且无法从 JSON 中清楚地识别出来,那么它将反序列化为第一个匹配的变体。简而言之,如果你也有例如随后的 JsonRpcParam::OtherString(String)
,然后将反序列化为 JsonRpcParam::String(String)
.
#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
pub enum JsonRpcParam {
String(String),
Int(u64),
Bool(bool),
Vec(Vec<String>),
}
如果您现在使用例如serde_json::to_string_pretty()
,然后它将以您想要的格式产生输出:
fn main() {
let mut params: Vec<JsonRpcParam> = Vec::new();
params.push(JsonRpcParam::String("Test".to_string()));
params.push(JsonRpcParam::Bool(true));
params.push(JsonRpcParam::Int(64));
params.push(JsonRpcParam::Vec(vec![
String::from("abc"),
String::from("cde"),
]));
let json = serde_json::to_string_pretty(¶ms).unwrap();
println!("{}", json);
}
输出:
[
"Test",
true,
64,
[
"abc",
"cde"
]
]