提问人:user2297996 提问时间:9/27/2023 最后编辑:Chayim Friedmanuser2297996 更新时间:9/27/2023 访问量:87
是否可以使用 Serde / Rust 全局处理无效的 JSON 值?
Is it possible to to handle invalid JSON values globally using Serde / Rust?
问:
我的意思是:
给定此结构:
struct SomeObj {
someProp: bool
}
有没有办法强制Serde在JSON输入中的值不是布尔值时分配true / false?someProp
通常,在这种情况下,serde 只会返回错误(无效类型,预期的 XY。等)。但是,是否可以抑制错误并仅提供一些有意义的默认值?
我知道这是可能的,比如:
#[serde(from = "serde_json::Value")]
struct SomeObj {
someProp: bool
}
impl From<serde_json::Value> for SomeObj {
...
}
但是我需要处理大量复杂而庞大的结构,因此在全球范围内处理这个问题会容易得多。
答:
2赞
Silvio Mayolo
9/27/2023
#1
您始终可以使用属性 deserialize_with
覆盖对反序列化程序的选择。此属性接受一个函数,该函数将用于反序列化,而不是通常的特征。serde
Deserialize
#[derive(Serialize, Deserialize)]
struct SomeObj {
#[serde(deserialize_with = "deserialize_bool_or_false")]
someProp: bool
}
fn deserialize_bool_or_false<'de, D>(deserializer: D) -> Result<bool, D::Error>
where D: Deserializer<'de> {
let deserialized = bool::deserialize(deserializer);
// deserialized is a Result<bool, ...>. You can handle the error
// case however you like. This example simply returns false.
Ok(deserialized.unwrap_or(false))
}
您只需将该属性附加到要自定义默认行为的每个字段。deserialize_with
如果您愿意引入额外的依赖项,serde_with
库具有 DefaultOnError
,如果该字段发生任何反序列化错误,它将返回类型(即 、 、 、 等)的 Default::d efault()
值。因此,使用该结构,您可以将任何字段标记为 并且,只要基础类型实现了 trait ,它就会起作用。false
""
0
0.0
#[serde_as(deserialize_as = "DefaultOnError")]
Default
#[serde_as]
#[derive(Serialize, Deserialize)]
struct SomeObj {
#[serde_as(deserialize_as = "DefaultOnError")]
someProp: bool
}
这将适用于任何有符号或无符号整数类型、浮点类型、字符串以及任何满足 .bool
Default
评论
0赞
user2297996
9/27/2023
谢谢。这听起来比为每个结构/枚举实现 From 要好得多。但我想这仍然意味着我必须创建一堆自定义反序列化程序,然后手动将它们附加到每个字段。所以没有“简单的方法”可以解决这个问题,对吧?就像以某种方式告诉 serde 如何处理布尔值、字符串、数字等字段一次,然后在任何地方使用它。
0赞
Silvio Mayolo
9/27/2023
@user2297996 看看我刚刚对答案所做的编辑。我以为可以干净利落地做到这一点,我找到了。 应该适用于几乎任何合理的 JSON 类型,只要您想要的“默认”值是由 Rust 的特征定义的值。serde_with
DefaultOnError
Default
0赞
user2297996
9/27/2023
完善!谢谢,这听起来很棒!我会这样做的。
评论
"yes"
"no"