rust – 将JSON字符串或字符串数​​组反序列化为Vec

我正在编写一个与JSON Web API接口的包.一个端点通常返回{“key”形式的响应:[“value1”,“value2”]},但有时键只有一个值,端点返回{“key”:“value”}而不是{ “核心价值”] }

我想写一些通用的东西,我可以使用#[serde(deserialize_with)],如下所示:

#[derive(Deserialize)]
struct SomeStruct {
    #[serde(deserialize_with = "deserialize_string_or_seq_string")]
    field1: Vec<SomeStringNewType>,

    #[serde(deserialize_with = "deserialize_string_or_seq_string")]
    field2: Vec<SomeTypeWithCustomDeserializeFromStr>,
}

#[derive(Deserialize)]
struct SomeStringNewType(String);

struct SomeTypeWithCustomDeserializeFromStr(String);
impl ::serde::de::Deserialize for SomeTypeWithCustomDeserializeFromStr {
    // Some custom implementation here
}

如何编写deserialize_string_or_seq_string才能执行此操作?

最佳答案
如果您想将单个字符串或字符串列表反序列化为更一般的Vec< String>而不是自定义类型,以下是Serde 1.0的更简单的解决方案:

extern crate serde;
#[macro_use] extern crate serde_derive;
extern crate serde_json;

use std::fmt;
use std::marker::PhantomData;

use serde::de;
use serde::de::{Deserialize, Deserializer};

#[derive(Deserialize, Debug, Clone)]
pub struct Parent {
    #[serde(deserialize_with = "string_or_seq_string")]
    pub strings: Vec<String>,
}

fn main() {
    let list_of_strings: Parent = serde_json::from_str(r#"{ "strings": ["value1", "value2"] }"#).unwrap();
    println!("list of strings: {:?}", list_of_strings);
    // Prints:
    //   list of strings: Parent { strings: ["value1", "value2"] }

    let single_string: Parent = serde_json::from_str(r#"{ "strings": "value" }"#).unwrap();
    println!("single string: {:?}", single_string);
    // Prints:
    //   single string: Parent { strings: ["value"] }
}

fn string_or_seq_string<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
    where D: Deserializer<'de>
{
    struct StringOrVec(PhantomData<Vec<String>>);

    impl<'de> de::Visitor<'de> for StringOrVec {
        type Value = Vec<String>;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            formatter.write_str("string or list of strings")
        }

        fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
            where E: de::Error
        {
            Ok(vec![value.to_owned()])
        }

        fn visit_seq<S>(self, visitor: S) -> Result<Self::Value, S::Error>
            where S: de::SeqAccess<'de>
        {
            Deserialize::deserialize(de::value::SeqAccessDeserializer::new(visitor))
        }
    }

    deserializer.deserialize_any(StringOrVec(PhantomData))
}

此解决方案也适用于Serde的0.9版本,并进行了以下更改:

>消除生命
> SeqAccess – > SeqVisitor
> SeqAccessDeserializer – > SeqVisitorDeserializer
> MapAccess – > MapVisitor
> MapAccessDeserializer – > MapVisitorDeserializer

转载注明原文:rust – 将JSON字符串或字符串数​​组反序列化为Vec - 代码日志