use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ArrayOrJson {
ArrayValue(Vec<serde_json::Value>),
SingleValue(serde_json::Value),
}
impl std::fmt::Display for ArrayOrJson {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
ArrayOrJson::SingleValue(s) => write!(f, "{}", s),
ArrayOrJson::ArrayValue(v) => write!(
f,
"{}",
v.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join(", ")
),
}
}
}
impl ArrayOrJson {
pub fn as_vec(&self) -> Vec<serde_json::Value> {
match self {
ArrayOrJson::SingleValue(s) => vec![s.clone()],
ArrayOrJson::ArrayValue(v) => v.clone(),
}
}
}
impl Default for ArrayOrJson {
fn default() -> Self {
ArrayOrJson::ArrayValue(Vec::new())
}
}
impl From<serde_json::Value> for ArrayOrJson {
fn from(s: serde_json::Value) -> Self {
ArrayOrJson::SingleValue(s)
}
}
impl From<Vec<serde_json::Value>> for ArrayOrJson {
fn from(v: Vec<serde_json::Value>) -> Self {
ArrayOrJson::ArrayValue(v)
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::{from_str, json, to_string};
#[derive(Debug, Deserialize, Serialize, Default)]
struct WaitWrapper {
#[serde(default)]
wait: ArrayOrJson,
}
#[test]
fn test_deserialize_number() {
let json = r#"{"wait": {"name":"0"}}"#;
let obj: WaitWrapper = from_str(json).unwrap();
assert_eq!(obj.wait, ArrayOrJson::SingleValue(json!({"name": "0"})));
}
#[test]
fn test_deserialize_string() {
let json = r#"{"wait": []}"#;
let obj: WaitWrapper = from_str(json).unwrap();
assert_eq!(obj.wait, ArrayOrJson::ArrayValue(Vec::new()));
}
#[test]
fn test_default_value() {
let json = r#"{}"#;
let obj: WaitWrapper = from_str(json).unwrap();
assert_eq!(obj.wait, ArrayOrJson::default());
}
#[test]
fn test_from_conversions() {
let a: ArrayOrJson = json!({"name": "0"}).into();
let b: ArrayOrJson = vec![json!({"name": "0"})].into();
assert_eq!(a, ArrayOrJson::SingleValue(json!({"name": "0"})));
assert_eq!(b, ArrayOrJson::ArrayValue(vec![json!({"name": "0"})]));
}
#[test]
fn test_serialization() {
let a = WaitWrapper {
wait: json!({"name": "0"}).into(),
};
let b = WaitWrapper {
wait: vec![json!({"name": "0"})].into(),
};
assert_eq!(to_string(&a).unwrap(), r#"{"wait":{"name":"0"}}"#);
assert_eq!(to_string(&b).unwrap(), r#"{"wait":[{"name":"0"}]}"#);
}
}