jsonschema_valid/
schemas.rs

1//! Implementations of the different drafts of JSON schema.
2//!
3
4use lazy_static::lazy_static;
5use serde_json::Value;
6
7use crate::format;
8use crate::format::FormatChecker;
9use crate::validators;
10use crate::validators::Validator;
11
12/// The validator can validate JSON data against different versions of JSON Schema.
13#[derive(Debug, Copy, Clone, PartialEq, Eq)]
14pub enum Draft {
15    /// JSONSchema [Draft 4](https://json-schema.org/specification-links.html#draft-4)
16    Draft4,
17
18    /// JSONSchema [Draft 6](https://json-schema.org/specification-links.html#draft-6)
19    Draft6,
20
21    /// JSONSchema [Draft 7](https://json-schema.org/specification-links.html#draft-7)
22    Draft7,
23}
24
25impl Draft {
26    pub(crate) fn get_validator(self, key: &str) -> Option<Validator> {
27        match self {
28            Draft::Draft4 => draft4::get_validator(key),
29            Draft::Draft6 => draft6::get_validator(key),
30            Draft::Draft7 => draft7::get_validator(key),
31        }
32    }
33
34    /// Get the JSON representation of the schema document.
35    pub fn get_schema(self) -> &'static Value {
36        match self {
37            Draft::Draft7 => draft7::get_schema(),
38            Draft::Draft6 => draft6::get_schema(),
39            Draft::Draft4 => draft4::get_schema(),
40        }
41    }
42
43    /// Get a format check function.
44    pub(crate) fn get_format_checker(self, format: &str) -> Option<FormatChecker> {
45        match self {
46            Draft::Draft4 => draft4::get_format_checker(format),
47            Draft::Draft6 => draft6::get_format_checker(format),
48            Draft::Draft7 => draft7::get_format_checker(format),
49        }
50    }
51
52    /// Return the draft's number.
53    pub fn get_draft_number(self) -> u8 {
54        match self {
55            Draft::Draft4 => 4,
56            Draft::Draft6 => 6,
57            Draft::Draft7 => 7,
58        }
59    }
60}
61
62mod draft7 {
63    use super::*;
64
65    pub(super) fn get_validator(key: &str) -> Option<Validator> {
66        match key {
67            "$ref" => Some(validators::ref_ as Validator),
68            "additionalItems" => Some(validators::additionalItems as Validator),
69            "additionalProperties" => Some(validators::additionalProperties as Validator),
70            "allOf" => Some(validators::allOf as Validator),
71            "anyOf" => Some(validators::anyOf as Validator),
72            "const" => Some(validators::const_ as Validator),
73            "contains" => Some(validators::contains as Validator),
74            "dependencies" => Some(validators::dependencies as Validator),
75            "enum" => Some(validators::enum_ as Validator),
76            "exclusiveMaximum" => Some(validators::exclusiveMaximum as Validator),
77            "exclusiveMinimum" => Some(validators::exclusiveMinimum as Validator),
78            "format" => Some(validators::format as Validator),
79            "if" => Some(validators::if_ as Validator),
80            "items" => Some(validators::items as Validator),
81            "maxItems" => Some(validators::maxItems as Validator),
82            "maxLength" => Some(validators::maxLength as Validator),
83            "maxProperties" => Some(validators::maxProperties as Validator),
84            "maximum" => Some(validators::maximum as Validator),
85            "minItems" => Some(validators::minItems as Validator),
86            "minLength" => Some(validators::minLength as Validator),
87            "minProperties" => Some(validators::minProperties as Validator),
88            "minimum" => Some(validators::minimum as Validator),
89            "multipleOf" => Some(validators::multipleOf as Validator),
90            "not" => Some(validators::not as Validator),
91            "oneOf" => Some(validators::oneOf as Validator),
92            "pattern" => Some(validators::pattern as Validator),
93            "patternProperties" => Some(validators::patternProperties as Validator),
94            "properties" => Some(validators::properties as Validator),
95            "propertyNames" => Some(validators::propertyNames as Validator),
96            "required" => Some(validators::required as Validator),
97            "type" => Some(validators::type_ as Validator),
98            "uniqueItems" => Some(validators::uniqueItems as Validator),
99            _ => None,
100        }
101    }
102
103    pub(super) fn get_schema() -> &'static Value {
104        lazy_static! {
105            static ref DRAFT7: Value = serde_json::from_str(include_str!("draft7.json")).unwrap();
106        }
107        &DRAFT7
108    }
109
110    pub(super) fn get_format_checker(key: &str) -> Option<FormatChecker> {
111        match key {
112            "date" => Some(format::date as FormatChecker),
113            "date-time" => Some(format::datetime as FormatChecker),
114            "email" => Some(format::email as FormatChecker),
115            "hostname" => Some(format::hostname as FormatChecker),
116            "idn-email" => Some(format::email as FormatChecker),
117            "ipv4" => Some(format::ipv4 as FormatChecker),
118            "ipv6" => Some(format::ipv6 as FormatChecker),
119            "iri" => Some(format::iri as FormatChecker),
120            "iri-reference" => Some(format::iri_reference as FormatChecker),
121            "json-pointer" => Some(format::json_pointer as FormatChecker),
122            "regex" => Some(format::regex as FormatChecker),
123            "time" => Some(format::time as FormatChecker),
124            "uri" => Some(format::uri as FormatChecker),
125            "uri-reference" => Some(format::uri_reference as FormatChecker),
126            "uri-template" => Some(format::uri_template as FormatChecker),
127            _ => None,
128        }
129    }
130}
131
132mod draft6 {
133    use super::*;
134
135    pub(super) fn get_validator(key: &str) -> Option<Validator> {
136        match key {
137            "$ref" => Some(validators::ref_ as Validator),
138            "additionalItems" => Some(validators::additionalItems as Validator),
139            "additionalProperties" => Some(validators::additionalProperties as Validator),
140            "allOf" => Some(validators::allOf as Validator),
141            "anyOf" => Some(validators::anyOf as Validator),
142            "const" => Some(validators::const_ as Validator),
143            "contains" => Some(validators::contains as Validator),
144            "dependencies" => Some(validators::dependencies as Validator),
145            "enum" => Some(validators::enum_ as Validator),
146            "exclusiveMaximum" => Some(validators::exclusiveMaximum as Validator),
147            "exclusiveMinimum" => Some(validators::exclusiveMinimum as Validator),
148            "format" => Some(validators::format as Validator),
149            "items" => Some(validators::items as Validator),
150            "maxItems" => Some(validators::maxItems as Validator),
151            "maxLength" => Some(validators::maxLength as Validator),
152            "maxProperties" => Some(validators::maxProperties as Validator),
153            "maximum" => Some(validators::maximum as Validator),
154            "minItems" => Some(validators::minItems as Validator),
155            "minLength" => Some(validators::minLength as Validator),
156            "minProperties" => Some(validators::minProperties as Validator),
157            "minimum" => Some(validators::minimum as Validator),
158            "multipleOf" => Some(validators::multipleOf as Validator),
159            "not" => Some(validators::not as Validator),
160            "oneOf" => Some(validators::oneOf as Validator),
161            "pattern" => Some(validators::pattern as Validator),
162            "patternProperties" => Some(validators::patternProperties as Validator),
163            "properties" => Some(validators::properties as Validator),
164            "propertyNames" => Some(validators::propertyNames as Validator),
165            "required" => Some(validators::required as Validator),
166            "type" => Some(validators::type_ as Validator),
167            "uniqueItems" => Some(validators::uniqueItems as Validator),
168            _ => None,
169        }
170    }
171
172    pub(super) fn get_schema() -> &'static Value {
173        lazy_static! {
174            static ref DRAFT6: Value = serde_json::from_str(include_str!("draft6.json")).unwrap();
175        }
176        &DRAFT6
177    }
178
179    pub(super) fn get_format_checker(key: &str) -> Option<FormatChecker> {
180        match key {
181            "date" => Some(format::date as FormatChecker),
182            "date-time" => Some(format::datetime as FormatChecker),
183            "email" => Some(format::email as FormatChecker),
184            "hostname" => Some(format::hostname as FormatChecker),
185            "ipv4" => Some(format::ipv4 as FormatChecker),
186            "ipv6" => Some(format::ipv6 as FormatChecker),
187            "json-pointer" => Some(format::json_pointer as FormatChecker),
188            "regex" => Some(format::regex as FormatChecker),
189            "time" => Some(format::time as FormatChecker),
190            "uri" => Some(format::uri as FormatChecker),
191            "uri-reference" => Some(format::uri_reference as FormatChecker),
192            "uri-template" => Some(format::uri_template as FormatChecker),
193            _ => None,
194        }
195    }
196}
197
198mod draft4 {
199    use super::*;
200
201    pub(super) fn get_validator(key: &str) -> Option<Validator> {
202        match key {
203            "$ref" => Some(validators::ref_ as Validator),
204            "additionalItems" => Some(validators::additionalItems as Validator),
205            "additionalProperties" => Some(validators::additionalProperties as Validator),
206            "allOf" => Some(validators::allOf as Validator),
207            "anyOf" => Some(validators::anyOf as Validator),
208            "dependencies" => Some(validators::dependencies as Validator),
209            "enum" => Some(validators::enum_ as Validator),
210            "format" => Some(validators::format as Validator),
211            "items" => Some(validators::items as Validator),
212            "maxItems" => Some(validators::maxItems as Validator),
213            "maxLength" => Some(validators::maxLength as Validator),
214            "maxProperties" => Some(validators::maxProperties as Validator),
215            "maximum" => Some(validators::maximum_draft4 as Validator),
216            "minItems" => Some(validators::minItems as Validator),
217            "minLength" => Some(validators::minLength as Validator),
218            "minProperties" => Some(validators::minProperties as Validator),
219            "minimum" => Some(validators::minimum_draft4 as Validator),
220            "multipleOf" => Some(validators::multipleOf as Validator),
221            "not" => Some(validators::not as Validator),
222            "oneOf" => Some(validators::oneOf as Validator),
223            "pattern" => Some(validators::pattern as Validator),
224            "patternProperties" => Some(validators::patternProperties as Validator),
225            "properties" => Some(validators::properties as Validator),
226            "required" => Some(validators::required as Validator),
227            "type" => Some(validators::type_ as Validator),
228            "uniqueItems" => Some(validators::uniqueItems as Validator),
229            _ => None,
230        }
231    }
232
233    pub(super) fn get_schema() -> &'static Value {
234        lazy_static! {
235            static ref DRAFT4: Value = serde_json::from_str(include_str!("draft4.json")).unwrap();
236        }
237        &DRAFT4
238    }
239
240    pub(super) fn get_format_checker(key: &str) -> Option<FormatChecker> {
241        match key {
242            "date-time" => Some(format::datetime as FormatChecker),
243            "email" => Some(format::email as FormatChecker),
244            "hostname" => Some(format::hostname as FormatChecker),
245            "ipv4" => Some(format::ipv4 as FormatChecker),
246            "ipv6" => Some(format::ipv6 as FormatChecker),
247            "regex" => Some(format::regex as FormatChecker),
248            "uri" => Some(format::uri as FormatChecker),
249            _ => None,
250        }
251    }
252}
253
254/// Get the `Draft` from a JSON Schema URL.
255pub fn draft_from_url(url: &str) -> Option<Draft> {
256    match url {
257        "http://json-schema.org/draft-07/schema" => Some(Draft::Draft7),
258        "http://json-schema.org/draft-06/schema" => Some(Draft::Draft6),
259        "http://json-schema.org/draft-04/schema" => Some(Draft::Draft4),
260        _ => None,
261    }
262}
263
264/// Get the `Draft` from a JSON Schema.
265pub fn draft_from_schema(schema: &Value) -> Option<Draft> {
266    schema
267        .as_object()
268        .and_then(|x| x.get("$schema"))
269        .and_then(Value::as_str)
270        .and_then(draft_from_url)
271}