serde_valid/validation/object/
min_properties.rs

1use crate::{traits::Size, MinPropertiesError};
2
3/// Min size validation of the object properties.
4///
5/// See <https://json-schema.org/understanding-json-schema/reference/object.html#size>
6///
7/// ```rust
8/// use std::collections::HashMap;
9///
10/// use serde_json::json;
11/// use serde_valid::{Validate, ValidateMinProperties};
12///
13/// struct MyType(HashMap<String, String>);
14///
15/// impl ValidateMinProperties for MyType {
16///     fn validate_min_properties(
17///         &self,
18///         min_properties: usize,
19///     ) -> Result<(), serde_valid::MinPropertiesError> {
20///         self.0.validate_min_properties(min_properties)
21///     }
22/// }
23///
24/// #[derive(Validate)]
25/// struct TestStruct {
26///     #[validate(min_properties = 2)]
27///     val: MyType,
28/// }
29///
30/// let mut map = HashMap::new();
31/// map.insert("key1".to_string(), "value1".to_string());
32///
33/// let s = TestStruct { val: MyType(map) };
34///
35/// assert_eq!(
36///     s.validate().unwrap_err().to_string(),
37///     json!({
38///         "errors": [],
39///         "properties": {
40///             "val": {
41///                 "errors": ["The size of the properties must be `>= 2`."]
42///             }
43///         }
44///     })
45///     .to_string()
46/// );
47/// ```
48pub trait ValidateMinProperties {
49    fn validate_min_properties(&self, min_properties: usize) -> Result<(), MinPropertiesError>;
50}
51
52impl<T> ValidateMinProperties for T
53where
54    T: Size,
55{
56    fn validate_min_properties(&self, min_properties: usize) -> Result<(), MinPropertiesError> {
57        if min_properties <= self.size() {
58            Ok(())
59        } else {
60            Err(MinPropertiesError::new(min_properties))
61        }
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68    use serde_json::json;
69    use std::collections::BTreeMap;
70    use std::collections::HashMap;
71
72    #[test]
73    fn test_validate_object_min_properties_hash_map_type() {
74        let mut map = HashMap::new();
75        map.insert("key1".to_string(), "value1".to_string());
76        map.insert("key2".to_string(), "value2".to_string());
77        map.insert("key3".to_string(), "value3".to_string());
78        assert!(ValidateMinProperties::validate_min_properties(&map, 3).is_ok());
79    }
80
81    #[test]
82    fn test_validate_object_min_properties_btree_map_type() {
83        let mut map = BTreeMap::new();
84        map.insert("key1".to_string(), "value1".to_string());
85        map.insert("key2".to_string(), "value2".to_string());
86        map.insert("key3".to_string(), "value3".to_string());
87        assert!(ValidateMinProperties::validate_min_properties(&map, 3).is_ok());
88    }
89
90    #[test]
91    fn test_validate_object_min_properties_json_map_type() {
92        let value = json!({
93            "key1": "value1",
94            "key2": "value2",
95            "key3": "value3",
96        });
97        let map = value.as_object().unwrap();
98
99        assert!(ValidateMinProperties::validate_min_properties(map, 2).is_ok());
100        assert!(ValidateMinProperties::validate_min_properties(map, 3).is_ok());
101    }
102
103    #[test]
104    fn test_validate_object_min_properties_is_false() {
105        let value = json!({
106            "key1": "value1",
107            "key2": "value2",
108            "key3": "value3",
109        });
110        let map = value.as_object().unwrap();
111
112        assert!(ValidateMinProperties::validate_min_properties(map, 4).is_err());
113    }
114}