gpt4 book ai didi

rust - 如何区分缺少的反序列化字段和空字段?

转载 作者:行者123 更新时间:2023-11-29 07:43:07 26 4
gpt4 key购买 nike

我想使用 Serde解析一些 JSON 作为 HTTP PATCH 请求的一部分。由于 PATCH 请求不传递整个对象,只传递要更新的相关数据,因此我需要能够区分未传递的值、显式设置为 null 的值和存在的值(value)。

我有一个包含多个可为空字段的值对象:

struct Resource {
a: Option<i32>,
b: Option<i32>,
c: Option<i32>,
}

如果客户端像这样提交JSON:

{"a": 42, "b": null}

我想将a更改为Some(42),将b更改为None,然后离开c 不变。

我尝试将每个字段包装在多一层 Option 中:

#[derive(Debug, Deserialize)]
struct ResourcePatch {
a: Option<Option<i32>>,
b: Option<Option<i32>>,
c: Option<Option<i32>>,
}

playground

这里不区分bc;两者都是 None 但我希望 b 成为 Some(None)

我不受这种嵌套 Option 表示的束缚;任何可以区分这 3 种情况的解决方案都可以,例如使用自定义枚举的解决方案。

最佳答案

建立于 E_net4's answer ,您还可以为三种可能性创建一个枚举:

#[derive(Debug)]
enum Patch<T> {
Missing,
Null,
Value(T),
}

impl<T> Default for Patch<T> {
fn default() -> Self {
Patch::Missing
}
}

impl<T> From<Option<T>> for Patch<T> {
fn from(opt: Option<T>) -> Patch<T> {
match opt {
Some(v) => Patch::Value(v),
None => Patch::Null,
}
}
}

impl<'de, T> Deserialize<'de> for Patch<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Option::deserialize(deserializer).map(Into::into)
}
}

这可以用作:

#[derive(Debug, Deserialize)]
struct ResourcePatch {
#[serde(default)]
a: Patch<i32>,
}

不幸的是,您仍然必须使用 #[serde(default)] 注释每个字段(或将其应用于整个结构)。理想情况下,PatchDeserialize 实现可以完全解决这个问题,但我还没有想出如何做到这一点。

关于rust - 如何区分缺少的反序列化字段和空字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44331037/

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