mirror of
https://github.com/euzu/tuliprox.git
synced 2026-09-30 13:02:10 +02:00
86 lines
2.4 KiB
Rust
86 lines
2.4 KiB
Rust
use serde::{Deserialize, Deserializer,};
|
|
use serde::de::DeserializeOwned;
|
|
use serde_json::Value;
|
|
|
|
fn value_to_string_array(value: &[Value]) -> Vec<String> {
|
|
value.iter().filter_map(value_to_string).collect()
|
|
}
|
|
|
|
fn value_to_string(v: &Value) -> Option<String> {
|
|
match v {
|
|
Value::Bool(value) => Some(value.to_string()),
|
|
Value::Number(value) => Some(value.to_string()),
|
|
Value::String(value) => Some(value.to_string()),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
pub fn deserialize_as_option_rc_string<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
let value: Value = Deserialize::deserialize(deserializer)?;
|
|
|
|
match &value {
|
|
Value::String(s) => Ok(Some(s.to_owned())),
|
|
Value::Number(s) => Ok(Some(s.to_string())),
|
|
_ => Ok(None),
|
|
}
|
|
}
|
|
|
|
pub fn deserialize_as_rc_string<'de, D>(deserializer: D) -> Result<String, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
let value: Value = Deserialize::deserialize(deserializer)?;
|
|
|
|
match &value {
|
|
Value::String(s) => Ok(s.to_string()),
|
|
Value::Null => Ok(String::new()),
|
|
_ => Ok(value.to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn deserialize_as_string_array<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
Value::deserialize(deserializer).map(|v| match v {
|
|
Value::String(value) => Some(vec![value]),
|
|
Value::Array(value) => Some(value_to_string_array(&value)),
|
|
_ => None,
|
|
})
|
|
}
|
|
|
|
|
|
pub fn deserialize_number_from_string<'de, D, T: DeserializeOwned>(
|
|
deserializer: D,
|
|
) -> Result<Option<T>, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
// we define a local enum type inside of the function
|
|
// because it is untagged, serde will deserialize as the first variant
|
|
// that it can
|
|
#[derive(Deserialize)]
|
|
#[serde(untagged)]
|
|
enum MaybeNumber<U> {
|
|
// if it can be parsed as Option<T>, it will be
|
|
Value(Option<U>),
|
|
// otherwise try parsing as a string
|
|
NumberString(String),
|
|
}
|
|
|
|
// deserialize into local enum
|
|
let value: MaybeNumber<T> = Deserialize::deserialize(deserializer)?;
|
|
match value {
|
|
// if parsed as T or None, return that
|
|
MaybeNumber::Value(value) => Ok(value),
|
|
|
|
// (if it is any other string)
|
|
MaybeNumber::NumberString(string) => {
|
|
serde_json::from_str::<T>(string.as_str()).map_or_else(|_| Ok(None), |val| Ok(Some(val)))
|
|
}
|
|
}
|
|
}
|