栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何将Serde与具有不同对象的JSON数组配合使用以获取成功和错误?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何将Serde与具有不同对象的JSON数组配合使用以获取成功和错误?

这是一种方法:

#[macro_use]extern crate serde_derive; // 1.0.70extern crate serde; // 1.0.70extern crate serde_json; // 1.0.24#[derive(Serialize, Deserialize, Debug)]pub struct MyError {    error: String,}#[derive(Serialize, Deserialize, Debug)]pub struct MyAge {    age: i32,    name: String,}#[derive(Debug)]enum AgeOrError {    Age(MyAge),    Error(MyError),}impl serde::Serialize for AgeOrError {    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {        match self { &AgeOrError::Age(ref my_age) => serializer.serialize_some(my_age), &AgeOrError::Error(ref my_error) => serializer.serialize_some(my_error),        }    }}enum AgeOrErrorField {    Age,    Name,    Error,}impl<'de> serde::Deserialize<'de> for AgeOrErrorField {    fn deserialize<D>(deserializer: D) -> Result<AgeOrErrorField, D::Error>    where        D: serde::Deserializer<'de>,    {        struct AgeOrErrorFieldVisitor;        impl<'de> serde::de::Visitor<'de> for AgeOrErrorFieldVisitor { type Value = AgeOrErrorField; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {     write!(formatter, "age or error") } fn visit_str<E>(self, value: &str) -> Result<AgeOrErrorField, E> where     E: serde::de::Error, {     Ok(match value {         "age" => AgeOrErrorField::Age,         "name" => AgeOrErrorField::Name,         "error" => AgeOrErrorField::Error,         _ => panic!("Unexpected field name: {}", value),     }) }        }        deserializer.deserialize_any(AgeOrErrorFieldVisitor)    }}impl<'de> serde::Deserialize<'de> for AgeOrError {    fn deserialize<D>(deserializer: D) -> Result<AgeOrError, D::Error>    where        D: serde::Deserializer<'de>,    {        deserializer.deserialize_map(AgeOrErrorVisitor)    }}struct AgeOrErrorVisitor;impl<'de> serde::de::Visitor<'de> for AgeOrErrorVisitor {    type Value = AgeOrError;    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {        write!(formatter, "age or error")    }    fn visit_map<A>(self, mut map: A) -> Result<AgeOrError, A::Error>    where        A: serde::de::MapAccess<'de>,    {        let mut age: Option<i32> = None;        let mut name: Option<String> = None;        let mut error: Option<String> = None;        loop { match map.next_key()? {     Some(AgeOrErrorField::Age) => age = map.next_value()?,     Some(AgeOrErrorField::Name) => name = map.next_value()?,     Some(AgeOrErrorField::Error) => error = map.next_value()?,     None => break, }        }        if let Some(error) = error { Ok(AgeOrError::Error(MyError { error: error }))        } else { Ok(AgeOrError::Age(MyAge {     age: age.expect("!age"),     name: name.expect("!name"), }))        }    }}fn get_results(ages: &[i32]) -> Vec<AgeOrError> {    let mut results = Vec::with_capacity(ages.len());    for &age in ages.iter() {        if age < 100 && age > 0 { results.push(AgeOrError::Age(MyAge {     age: age,     name: String::from("The dude"), }));        } else { results.push(AgeOrError::Error(MyError {     error: format!("{} is invalid age", age), }));        }    }    results}fn main() {    let v = get_results(&[1, -6, 7]);    let serialized = serde_json::to_string(&v).expect("Can't serialize");    println!("serialized: {}", serialized);    let deserialized: Vec<AgeOrError> =        serde_json::from_str(&serialized).expect("Can't deserialize");    println!("deserialized: {:?}", deserialized);}

请注意,在反序列化中,我们不能重复使用自动生成的反序列化器,因为:

  1. 反序列化是一种将字段流式传输给我们的方法,我们无法 窥视 字符串化的JSON表示并猜测其含义。

  2. 我们无权访问

    serde::de::Visitor
    Serde生成的实现。

我也做了一个捷径,并

panic
在错误上加油。在生产代码中,您想返回正确的Serde错误。


另一个解决方案是使所有字段都为可选的合并结构,如下所示:

#[macro_use]extern crate serde_derive; // 1.0.70extern crate serde; // 1.0.70extern crate serde_json; // 1.0.24#[derive(Debug)]pub struct MyError {    error: String,}#[derive(Debug)]pub struct MyAge {    age: i32,    name: String,}#[derive(Serialize, Deserialize, Debug)]pub struct MyAgeOrError {    #[serde(skip_serializing_if = "Option::is_none")]    age: Option<i32>,    #[serde(skip_serializing_if = "Option::is_none")]    name: Option<String>,    #[serde(skip_serializing_if = "Option::is_none")]    error: Option<String>,}impl MyAgeOrError {    fn from_age(age: MyAge) -> MyAgeOrError {        MyAgeOrError { age: Some(age.age), name: Some(age.name), error: None,        }    }    fn from_error(error: MyError) -> MyAgeOrError {        MyAgeOrError { age: None, name: None, error: Some(error.error),        }    }}fn get_results(ages: &[i32]) -> Vec<MyAgeOrError> {    let mut results = Vec::with_capacity(ages.len());    for &age in ages.iter() {        if age < 100 && age > 0 { results.push(MyAgeOrError::from_age(MyAge {     age: age,     name: String::from("The dude"), }));        } else { results.push(MyAgeOrError::from_error(MyError {     error: format!("{} is invalid age", age), }));        }    }    results}fn main() {    let v = get_results(&[1, -6, 7]);    let serialized = serde_json::to_string(&v).expect("Can't serialize");    println!("serialized: {}", serialized);    let deserialized: Vec<MyAgeOrError> =        serde_json::from_str(&serialized).expect("Can't deserialize");    println!("deserialized: {:?}", deserialized);}

我对此表示保证,因为它允许Rust结构(例如

MyAgeOrError
)匹配JSON的布局。这样,JSON布局就被记录在Rust代码中。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/449202.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号