valico/json_schema/validators/
properties.rs
1use serde_json::{Value};
2use regex;
3use std::collections;
4use url;
5
6use super::super::errors;
7use super::super::scope;
8
9#[derive(Debug)]
10pub enum AdditionalKind {
11 Boolean(bool),
12 Schema(url::Url)
13}
14
15#[allow(missing_copy_implementations)]
16pub struct Properties {
17 pub properties: collections::HashMap<String, url::Url>,
18 pub additional: AdditionalKind,
19 pub patterns: Vec<(regex::Regex, url::Url)>
20}
21
22impl super::Validator for Properties {
23 fn validate(&self, val: &Value, path: &str, scope: &scope::Scope) -> super::ValidationState {
24 let object = nonstrict_process!(val.as_object(), path);
25 let mut state = super::ValidationState::new();
26
27 'main: for (key, value) in object.iter() {
28 let mut is_property_passed = false;
29 if self.properties.contains_key(key) {
30 let url = self.properties.get(key).unwrap();
31 let schema = scope.resolve(url);
32 if schema.is_some() {
33 let value_path = [path, key.as_ref()].join("/");
34 state.append(schema.unwrap().validate_in(value, value_path.as_ref()))
35 } else {
36 state.missing.push(url.clone())
37 }
38
39 is_property_passed = true;
40 }
41
42 let mut is_pattern_passed = false;
43 for &(ref regex, ref url) in self.patterns.iter() {
44 if regex.is_match(key.as_ref()) {
45 let schema = scope.resolve(url);
46 if schema.is_some() {
47 let value_path = [path, key.as_ref()].join("/");
48 state.append(schema.unwrap().validate_in(value, value_path.as_ref()));
49 is_pattern_passed = true;
50 } else {
51 state.missing.push(url.clone())
52 }
53 }
54 }
55
56 if is_property_passed || is_pattern_passed {
57 continue 'main;
58 }
59
60 match self.additional {
61 AdditionalKind::Boolean(allowed) if allowed == false => {
62 state.errors.push(Box::new(
63 errors::Properties {
64 path: path.to_string(),
65 detail: "Additional properties are not allowed".to_string()
66 }
67 ))
68 },
69 AdditionalKind::Schema(ref url) => {
70 let schema = scope.resolve(url);
71
72 if schema.is_some() {
73 let value_path = [path, key.as_ref()].join("/");
74 state.append(schema.unwrap().validate_in(value, value_path.as_ref()))
75 } else {
76 state.missing.push(url.clone())
77 }
78 },
79 _ => ()
81 }
82 }
83
84 state
85 }
86}