gpt4 book ai didi

error-handling - 如何在不使整个反序列化失败的情况下使用 Serde 解析可能无法反序列化的字段?

转载 作者:行者123 更新时间:2023-12-03 11:27:10 25 4
gpt4 key购买 nike

我正在反序列化一些作为请求传入的 JSON 对象。输入正文是嵌套的,但是某个字段有时会因为各种原因格式错误。在那种情况下,我仍然想要该对象的其余部分。这并不都必须通过 serde 来完成;但现在正在发生的事情是,如果一个子字段被搞砸了,整个请求都会被丢弃。我想以某种方式仍然反序列化该结果,并将该字段标记为错误。如何做到这一点?

例如数据模式可能如下所示:

struct BigNested {
a: Vec<A>,
b: B, // definition omitted
}

struct A {
keep_this: Foo,
trouble: SometimesBad,
}

trouble是经常出现困惑的领域。我很乐意(例如)转 trouble进入Result<SometimesBad, Whatever>并从那里处理它,但我不知道如何让 serde 让我这样做。

最佳答案

certain field is sometimes misformatted

您没有说明传入的 JSON 格式有多么畸形。假设它仍然是有效的 JSON,您可以使用 Serde's struct flatten 来解决这个问题和自定义反序列化:

  • 自定义反序列化以一种永远不会对有效 JSON 输入失败的方式完成,但如果输入具有意外格式,它可能不会返回预期类型的​​值。

  • 但这些意想不到的领域仍然需要去某个地方。 Serde 的结构 flatten因为 任何 JSON 片段都可以反序列化为 HashMap<String, Value>,所以在这里可以派上用场来捕获它们.

//# serde = { version = "1.0.103", features = ["derive"] }
//# serde_json = "1.0.44"
use serde::{Deserialize, Deserializer, de::DeserializeOwned};
use serde_json::Value;
use std::collections::HashMap;

#[derive(Deserialize, Debug)]
struct A {
keep_this: Foo,
trouble: SometimesBad,
}

#[derive(Deserialize, Debug)]
struct Foo {
foo: i32,
}

#[derive(Deserialize, Debug)]
struct SometimesBad {
inner: TryParse<Bar>,

#[serde(flatten)]
blackhole: HashMap<String, Value>,
}

#[derive(Deserialize, Debug)]
struct Bar {
bar: String,
}

#[derive(Debug)]
enum TryParse<T> {
Parsed(T),
Unparsed(Value),
NotPresent
}

impl<'de, T: DeserializeOwned> Deserialize<'de> for TryParse<T> {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
match Option::<Value>::deserialize(deserializer)? {
None => Ok(TryParse::NotPresent),
Some(value) => match T::deserialize(&value) {
Ok(t) => Ok(TryParse::Parsed(t)),
Err(_) => Ok(TryParse::Unparsed(value)),
},
}
}
}

fn main() {
let valid = r#"{ "keep_this": { "foo": 1 }, "trouble": { "inner": { "bar": "one"}}}"#;
println!("{:#?}", serde_json::from_str::<A>(valid));

let extra_field = r#"{ "keep_this": { "foo": 1 }, "trouble": { "inner": { "bar": "one"}, "extra": 2019}}"#;
println!("{:#?}", serde_json::from_str::<A>(extra_field));

let wrong_type = r#"{ "keep_this": { "foo": 1 }, "trouble": { "inner": { "bar": 1}}}"#;
println!("{:#?}", serde_json::from_str::<A>(wrong_type));

let missing_field = r#"{ "keep_this": { "foo": 1 }, "trouble": { "inner": { "baz": "one"}}}"#;
println!("{:#?}", serde_json::from_str::<A>(missing_field));

let missing_inner = r#"{ "keep_this": { "foo": 1 }, "trouble": { "whatever": { "bar": "one"}}}"#;
println!("{:#?}", serde_json::from_str::<A>(missing_inner));
}

(功劳不全是我的。Serde's issue 1583基本上什么都有。)

关于error-handling - 如何在不使整个反序列化失败的情况下使用 Serde 解析可能无法反序列化的字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64114043/

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