use serde::de::DeserializeOwned;
use serde_json::Value;
pub trait JsonValueExt {
fn parse_as<T: DeserializeOwned>(&self) -> Option<T>;
fn parse_or_default<T: DeserializeOwned + Default>(&self) -> T;
}
impl JsonValueExt for Option<Value> {
fn parse_as<T: DeserializeOwned>(&self) -> Option<T> {
self.as_ref()
.and_then(|v| serde_json::from_value(v.clone()).ok())
}
fn parse_or_default<T: DeserializeOwned + Default>(&self) -> T {
self.parse_as().unwrap_or_default()
}
}
impl JsonValueExt for Value {
fn parse_as<T: DeserializeOwned>(&self) -> Option<T> {
serde_json::from_value(self.clone()).ok()
}
fn parse_or_default<T: DeserializeOwned + Default>(&self) -> T {
self.parse_as().unwrap_or_default()
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde::Deserialize;
use serde_json::json;
#[derive(Debug, Deserialize, PartialEq)]
struct TestData {
name: String,
age: u32,
}
#[test]
fn test_parse_as_option_value_some() {
let value: Option<Value> = Some(json!({"name": "John", "age": 30}));
let result: Option<TestData> = value.parse_as();
assert_eq!(
result,
Some(TestData {
name: "John".to_string(),
age: 30
})
);
}
#[test]
fn test_parse_as_option_value_none() {
let value: Option<Value> = None;
let result: Option<TestData> = value.parse_as();
assert!(result.is_none());
}
#[test]
fn test_parse_as_option_value_invalid() {
let value: Option<Value> = Some(json!("not a struct"));
let result: Option<TestData> = value.parse_as();
assert!(result.is_none());
}
#[test]
fn test_parse_or_default_option_value() {
let value: Option<Value> = Some(json!(["a", "b", "c"]));
let result: Vec<String> = value.parse_or_default();
assert_eq!(result, vec!["a", "b", "c"]);
}
#[test]
fn test_parse_or_default_option_value_none() {
let value: Option<Value> = None;
let result: Vec<String> = value.parse_or_default();
assert!(result.is_empty());
}
#[test]
fn test_parse_as_value() {
let value = json!({"name": "Jane", "age": 25});
let result: Option<TestData> = value.parse_as();
assert_eq!(
result,
Some(TestData {
name: "Jane".to_string(),
age: 25
})
);
}
#[test]
fn test_parse_or_default_value() {
let value = json!([1, 2, 3]);
let result: Vec<i32> = value.parse_or_default();
assert_eq!(result, vec![1, 2, 3]);
}
#[test]
fn test_parse_or_default_value_invalid() {
let value = json!("not a vec");
let result: Vec<i32> = value.parse_or_default();
assert!(result.is_empty());
}
}