gpt4 book ai didi

rust - 如何将 serde_json 与联合类型(如枚举)一起使用?

转载 作者:行者123 更新时间:2023-12-04 07:51:13 25 4
gpt4 key购买 nike

我有两个结构,我想使用标记作为 JSON 中的 "type" 字段进行序列化/反序列化,就像这样。

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
struct ThingA {
value: usize,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
struct ThingB {
value: usize,
}

这些按预期序列化。例如,

let a = ThingA { value: 0 };
println!("{}", serde_json::to_string(&a)?);
// This yields the expected result:
// {"type":"ThingA","value":0}

但是,当我尝试添加一个枚举作为结构的联合类型时,我遇到了麻烦。

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
enum Thing {
ThingA(ThingA),
ThingB(ThingB),
}

上面的定义适用于反序列化 JSON,但在序列化期间添加了一个额外的字段。

let json = r#"{"type": "ThingB", "value": 0}"#;
let thing: Thing = serde_json::from_str(json)?;
// Correctly parses to:
// ThingB(ThingB { value: 0 })

println!("{}", serde_json::to_string(&thing)?);
// Incorrectly serializes with an extra "type" field:
// {"type":"ThingB","type":"ThingB","value":0}

Thing 枚举上的 #[serde(tag = "type")] 更改为 #[serde(untagged)] 会导致相反的问题:Thing 实例正确序列化,但不再正确解析。

我的目标是让 JSON {"type": "ThingB", value: 0} 评估为 Thing::ThingB(ThingB {value: 0}) 在反序列化期间,反之亦然,但前提是我反序列化为 Thing。如果我有一个未包装的 ThingB,比如 ThingB {value: 0},我希望它序列化为 {"type": "ThingB", value: 0 也是。

所以我的问题是:是否有任何方法可以分配 serde taguntagged 属性,以便它们仅在序列化/反序列化期间应用(类似于 serde 的 重命名)?如果没有,关于如何实现 Serialize 和/或 Deserialize 以实现我的目标有什么建议吗?

最佳答案

你可以在你的 Thing 枚举中使用 tag,其他的保持干净:

use serde::{Serialize, Deserialize}; // 1.0.124
use serde_json; // 1.0.64

#[derive(Debug, Clone, Serialize, Deserialize)]
struct ThingA {
value: usize,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
struct ThingB {
value: usize,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
enum Thing {
ThingA(ThingA),
ThingB(ThingB),
}

fn main() {
let json = r#"{"type": "ThingB", "value": 0}"#;
let thing: Thing = serde_json::from_str(json).unwrap();
println!("{}", serde_json::to_string(&thing).unwrap());

}

Playground

按照评论中的要求。如果我们想要同时标记(枚举和结构),我们需要制作一些 serde 咒语来玩包装器和 with。可以找到更多信息 here

关于rust - 如何将 serde_json 与联合类型(如枚举)一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66964692/

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