valico/json_schema/keywords/
of.rs

1use serde_json::{Value};
2
3use super::super::schema;
4use super::super::validators;
5use super::super::helpers;
6
7macro_rules! of_keyword{
8    ($name:ident, $kw:expr) => {
9
10        #[allow(missing_copy_implementations)]
11        pub struct $name;
12        impl super::Keyword for $name {
13            fn compile(&self, def: &Value, ctx: &schema::WalkContext) -> super::KeywordResult {
14                let of = keyword_key_exists!(def, $kw);
15
16                if of.is_array() {
17                    let of = of.as_array().unwrap();
18
19                    if of.len() == 0 {
20                        return Err(schema::SchemaError::Malformed {
21                            path: ctx.fragment.join("/"),
22                            detail: "This array MUST have at least one element.".to_string()
23                        })
24                    }
25
26                    let mut schemes = vec![];
27                    for (idx, scheme) in of.iter().enumerate() {
28                        if scheme.is_object() {
29                            schemes.push(
30                                helpers::alter_fragment_path(ctx.url.clone(), [
31                                    ctx.escaped_fragment().as_ref(),
32                                    $kw,
33                                    idx.to_string().as_ref()
34                                ].join("/"))
35                            )
36                        } else {
37                            return Err(schema::SchemaError::Malformed {
38                                path: ctx.fragment.join("/"),
39                                detail: "Elements of the array MUST be objects.".to_string()
40                            })
41                        }
42                    }
43
44                    Ok(Some(Box::new(validators::$name {
45                        schemes: schemes
46                    })))
47                } else {
48                    Err(schema::SchemaError::Malformed {
49                        path: ctx.fragment.join("/"),
50                        detail: "The value of this keyword MUST be an array.".to_string()
51                    })
52                }
53            }
54        }
55
56    }
57}
58
59of_keyword!(AllOf, "allOf");
60of_keyword!(AnyOf, "anyOf");
61of_keyword!(OneOf, "oneOf");
62
63#[cfg(test)] use super::super::scope;
64#[cfg(test)] use super::super::builder;
65#[cfg(test)] use serde_json::to_value;
66
67#[test]
68fn validate_all_of() {
69    let mut scope = scope::Scope::new();
70    let schema = scope.compile_and_return(builder::schema(|s| {
71        s.all_of(|all_of| {
72            all_of.push(|schema| {
73                schema.minimum(5f64, false);
74            });
75            all_of.push(|schema| {
76                schema.maximum(10f64, false);
77            });
78        });
79    }).into_json(), true).ok().unwrap();
80
81    assert_eq!(schema.validate(&to_value(&7).unwrap()).is_valid(), true);
82    assert_eq!(schema.validate(&to_value(&4).unwrap()).is_valid(), false);
83    assert_eq!(schema.validate(&to_value(&11).unwrap()).is_valid(), false);
84}
85
86#[test]
87fn validate_any_of() {
88    let mut scope = scope::Scope::new();
89    let schema = scope.compile_and_return(builder::schema(|s| {
90        s.any_of(|all_of| {
91            all_of.push(|schema| {
92                schema.maximum(5f64, false);
93            });
94            all_of.push(|schema| {
95                schema.maximum(10f64, false);
96            });
97        });
98    }).into_json(), true).ok().unwrap();
99
100    assert_eq!(schema.validate(&to_value(&5).unwrap()).is_valid(), true);
101    assert_eq!(schema.validate(&to_value(&10).unwrap()).is_valid(), true);
102    assert_eq!(schema.validate(&to_value(&11).unwrap()).is_valid(), false);
103}
104
105#[test]
106fn validate_one_of() {
107    let mut scope = scope::Scope::new();
108    let schema = scope.compile_and_return(builder::schema(|s| {
109        s.one_of(|all_of| {
110            all_of.push(|schema| {
111                schema.maximum(5f64, false);
112            });
113            all_of.push(|schema| {
114                schema.maximum(10f64, false);
115            });
116        });
117    }).into_json(), true).ok().unwrap();
118
119    assert_eq!(schema.validate(&to_value(&5).unwrap()).is_valid(), false);
120    assert_eq!(schema.validate(&to_value(&6).unwrap()).is_valid(), true);
121    assert_eq!(schema.validate(&to_value(&11).unwrap()).is_valid(), false);
122}