枚举类型的自定义 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(&params).unwrap();
    println!("{}", json);
}

输出:

[
  "Test", 
  true,   
  64,     
  [       
    "abc",
    "cde" 
  ]       
]