枚举类型的自定义 serde 序列化

Jak*_*ter 4 rust serde

我有以下数据结构,它应该能够保存字符串、u64 值、布尔值或字符串向量。

#[derive(Serialize, Deserialize)]
pub enum JsonRpcParam {
    String(String),
    Int(u64),
    Bool(bool),
    Vec(Vec<String>)
}
Run Code Online (Sandbox Code Playgroud)

此数据结构的用例是构建可以有多种类型的 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")]));
Run Code Online (Sandbox Code Playgroud)

我现在的问题是序列化。我使用serde_json作为序列化部分。上面发布的向量的默认序列化产生:

[
   {
      "String":"Test"
   },
   {
      "Bool":true
   },
   {
      "Int":64
   },
   {
      "Vec":[
         "abc",
         "cde"
      ]
   }
]
Run Code Online (Sandbox Code Playgroud)

相反,我希望序列化看起来像这样:

[
   "Test",
   true,
   64,
   ["abc","cde"]
]
Run Code Online (Sandbox Code Playgroud)

我尝试为此类型实现自定义序列化方法,但不知道如何实现我想要的,我的尝试如下所示:

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) => _
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Val*_*tin 6

Serialize您可以使用#[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>),
}
Run Code Online (Sandbox Code Playgroud)

如果您现在使用 eg 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(&params).unwrap();
    println!("{}", json);
}
Run Code Online (Sandbox Code Playgroud)

输出:

[
  "Test", 
  true,   
  64,     
  [       
    "abc",
    "cde" 
  ]       
]
Run Code Online (Sandbox Code Playgroud)