mod de; mod ser; pub use de::from_any; pub use ser::to_any; #[cfg(test)] mod test { use super::*; use crate::any; use crate::any::Any; use serde::{Deserialize, Serialize}; use serde_json::json; use std::collections::HashMap; fn roundtrip(any: &Any) -> Any { // encode let mut buf = String::new(); any.to_json(&mut buf); // decode Any::from_json(buf.as_str()).unwrap() } #[test] fn json_any_null() { let expected = Any::Null; let actual = roundtrip(&expected); assert_eq!(actual, expected); } #[test] fn json_any_bool() { for v in [true, false] { let expected = Any::Bool(v); let actual = roundtrip(&expected); assert_eq!(actual, expected); } } #[test] fn json_any_number() { for v in [1.8, -1.5, 0.2, 0.25, 2349464814556456.4] { let expected = Any::Number(v); let actual = roundtrip(&expected); assert_eq!(actual, expected); } } #[test] fn json_any_string() { for v in ["", "hello ", "hello \nworld", "hello \"world\"", "hello 😀"] { let expected = Any::String(v.into()); let actual = roundtrip(&expected); assert_eq!(actual, expected); } } #[test] fn json_any_array() { let expected = Any::from(vec![ Any::Number(-10.0), Any::String("hello \\world".into()), Any::Null, Any::Bool(true), ]); let actual = roundtrip(&expected); assert_eq!(actual, expected); } #[test] fn json_any_map() { let expected = Any::from(HashMap::from([ ("a".to_string(), Any::Number(-10.2)), ("b".to_string(), Any::String("hello world".into())), ("c".to_string(), Any::Null), ("d".to_string(), Any::Bool(true)), ("e".to_string(), Any::from(vec![Any::String("abc".into())])), ( "f".to_string(), Any::from(HashMap::from([("fa".to_string(), Any::Number(1.5))])), ), ])); let actual = roundtrip(&expected); assert_eq!(actual, expected); } #[test] fn test_struct_any_roundtrip() { #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] struct Test { bool: bool, int: i64, negative_int: i64, max_int: i64, min_int: i64, real_number: f64, max_number: f64, min_number: f64, null: Option, some: Option, undefined: Option, nested: Nested, enum_a: StringEnum, enum_b: StringEnum, enum_c: StringEnum, array: Vec>, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] struct Nested { int: i16, other: f32, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] enum StringEnum { VariantA, VariantB(String), VariantC { test: bool }, } let test = Test { bool: true, int: 1, negative_int: -1, max_int: i64::MAX, min_int: i64::MIN, real_number: -123.2387f64, max_number: f64::MIN, min_number: f64::MAX, null: None, some: Some(false), undefined: None, nested: Nested { int: 100, other: 100.0, }, enum_a: StringEnum::VariantA, enum_b: StringEnum::VariantB("test".to_string()), enum_c: StringEnum::VariantC { test: true }, array: vec![None, Some(Nested { int: 0, other: 0.0 }), None], }; assert_eq!(test, from_any(&to_any(&test).unwrap()).unwrap()) } #[test] fn test_enum_untagged_any_roundtrip() { #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] struct Test { enum_a: StringEnum, enum_b: StringEnum, enum_c: StringEnum, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(untagged)] enum StringEnum { VariantA, VariantB(String), VariantC { test: bool }, } let test = Test { enum_a: StringEnum::VariantA, enum_b: StringEnum::VariantB("test".to_string()), enum_c: StringEnum::VariantC { test: true }, }; assert_eq!(test, from_any(&to_any(&test).unwrap()).unwrap()) } #[test] fn test_any_to_json_roundtrip() { let any = Any::from(HashMap::from([ ("bool".into(), Any::from(true)), ("int".into(), Any::from(1)), ("negativeInt".into(), Any::from(-1)), ("maxInt".into(), Any::from(i64::MAX)), ("minInt".into(), Any::from(i64::MIN)), ("realNumber".into(), Any::from(-123.2387f64)), ("maxNumber".into(), Any::from(f64::MIN)), ("minNumber".into(), Any::from(f64::MAX)), ("null".into(), Any::Null), ( "map".into(), Any::from(HashMap::from([ ("bool".into(), Any::from(true)), ("int".into(), Any::from(1)), ("negativeInt".into(), Any::from(-1)), ("maxInt".into(), Any::from(i64::MAX)), ("minInt".into(), Any::from(i64::MIN)), ("realNumber".into(), Any::from(-123.2387f64)), ("maxNumber".into(), Any::from(f64::MIN)), ("minNumber".into(), Any::from(f64::MAX)), ("null".into(), Any::Null), ])), ), ( "key6".into(), Any::from(vec![ Any::from(true), Any::from(1), Any::from(-1), Any::from(i64::MAX), Any::from(i64::MIN), Any::from(-123.2387f64), Any::from(f64::MIN), Any::from(f64::MAX), Any::Null, ]), ), ])); assert_eq!( any, serde_json::from_str::(serde_json::to_string(&any).unwrap().as_str()).unwrap() ); } #[test] fn any_is_serde_json_convertible() { let any = any!({ "bool": true, "int": 1, "negativeInt": -1, "realNumber": -123.2387f64, "null": Any::Null, "map": { "bool": true, "int": 1, "negativeInt": -1, "realNumber": -123.2387f64, "null": Any::Null }, "key6":[ true, 1, -1, -123.2387f64, Any::Null ] }); let expected = json!({ "bool": true, "int": 1, "negativeInt": -1, "realNumber": -123.2387f64, "null": Any::Null, "map": { "bool": true, "int": 1, "negativeInt": -1, "realNumber": -123.2387f64, "null": Any::Null }, "key6":[ true, 1, -1, -123.2387f64, Any::Null ] }); let json = serde_json::to_value(&any).unwrap(); assert_eq!(json, expected); let any2: Any = serde_json::from_value(json).unwrap(); assert_eq!(any, any2); } }