1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use std::fmt::Display;
use std::str::FromStr;

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

pub mod bigquery_client;
pub mod bigquery_dataset_client;
pub mod bigquery_job_client;
pub mod bigquery_model_client;
pub mod bigquery_routine_client;
pub mod bigquery_row_access_policy_client;
pub mod bigquery_table_client;
pub mod bigquery_tabledata_client;
pub mod dataset;
pub mod error;
pub mod job;
pub mod model;
pub mod query;
pub mod routine;
pub mod row_access_policy;
pub mod table;
pub mod tabledata;
pub mod types;

fn from_str_option<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
where
    T: FromStr,
    T::Err: Display,
    D: Deserializer<'de>,
{
    let s: Result<Value, _> = Deserialize::deserialize(deserializer);
    match s {
        Ok(Value::String(s)) => T::from_str(&s).map_err(de::Error::custom).map(Some),
        Ok(_) => Err(de::Error::custom("Incorrect type")),
        Err(_) => Ok(None),
    }
}

pub fn from_str<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
    T: FromStr,
    T::Err: Display,
    D: de::Deserializer<'de>,
{
    let s = String::deserialize(deserializer)?;
    T::from_str(&s).map_err(de::Error::custom)
}

fn from_str_vec_option<'de, T, D>(deserializer: D) -> Result<Option<Vec<T>>, D::Error>
where
    T: FromStr,
    T::Err: Display,
    D: Deserializer<'de>,
{
    let s: Result<Value, _> = Deserialize::deserialize(deserializer);
    match s {
        Ok(Value::Array(vec)) => {
            let mut result = Vec::with_capacity(vec.len());
            for v in vec {
                let v = match v {
                    Value::String(s) => T::from_str(&s).map_err(de::Error::custom)?,
                    _ => return Err(de::Error::custom("Incorrect type")),
                };
                result.push(v);
            }
            Ok(Some(result))
        }
        Ok(_) => Err(de::Error::custom("Incorrect type")),
        Err(_) => Ok(None),
    }
}

fn from_str_vec<'de, T, D>(deserializer: D) -> Result<Vec<T>, D::Error>
where
    T: FromStr,
    T::Err: Display,
    D: Deserializer<'de>,
{
    let vec: Vec<String> = Vec::deserialize(deserializer)?;
    let mut result = Vec::with_capacity(vec.len());
    for v in vec {
        result.push(T::from_str(&v).map_err(de::Error::custom)?);
    }
    Ok(result)
}

#[cfg(test)]
mod test {

    #[derive(Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize, Debug, Default)]
    #[serde(rename_all = "camelCase")]
    struct Test {
        #[serde(default, deserialize_with = "crate::http::from_str_vec_option")]
        pub field: Option<Vec<i64>>,
    }

    #[test]
    fn test_from_str_vec_option() {
        let value: Test = serde_json::from_str(r#"{"field": ["100", "200"]}"#).unwrap();
        let record = value.field.unwrap();
        assert_eq!(vec![100, 200], record);

        let value: Test = serde_json::from_str(r#"{}"#).unwrap();
        assert!(value.field.is_none());
    }

    #[derive(Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize, Debug, Default)]
    #[serde(rename_all = "camelCase")]
    struct Test2 {
        #[serde(deserialize_with = "crate::http::from_str_vec")]
        pub field: Vec<i64>,
    }

    #[test]
    fn test_from_str_vec() {
        let value: Test2 = serde_json::from_str(r#"{"field": ["100", "200"]}"#).unwrap();
        assert_eq!(vec![100, 200], value.field);
        let result = serde_json::from_str::<Test2>(r#"{}"#);
        assert!(result.is_err())
    }
}