outlines_core/json_schema/
mod.rs

1//! Provides interfaces to generate a regular expression based on a given JSON schema.
2//!
3//! An optional custom pattern could be passed as well to handle whitespace within the regex.
4//! If `None`, the default [`WHITESPACE`] pattern is used.
5//!
6//! Returns errors if JSON schema's content is invalid or some feature is not yet supported
7//! for regex generation.
8//!
9//! ## Supported features
10//!
11//! Note, that only some of the features of JSON schema are supported for regex generation.
12//!
13//! ### Supported constraints
14//!
15//! #### Common
16//!  - `type`
17//!     - Specifies the data type (string, number, integer, boolean, array, object, null).
18//!  - `enum`
19//!     - Lists the allowed values.
20//!  - `const`
21//!     - Specifies a single allowed value.
22//!
23//! #### Object
24//! - `properties`
25//!     - Defines the expected properties of an object and their schemas.
26//! - `required`
27//!     - Lists the properties that must be present.
28//! - `additionalProperties`
29//!     - Specifies whether additional properties are allowed or defines their schema.
30//! - `minProperties`
31//!     - Minimum number of properties required.
32//! - `maxProperties`
33//!     - Maximum number of properties allowed.
34//!
35//! #### Array
36//! - `items`
37//!     - Defines the schema for array elements (single schema or a schema per index).
38//! - `prefixItems`
39//!     - Specifies schemas for the first few elements of an array (tuple validation).
40//! - `minItems`
41//!     - Minimum number of items required in the array.
42//! - `maxItems`
43//!     - Maximum number of items allowed in the array.
44//!
45//! #### String
46//! - `minLength`
47//!     - Minimum string length.
48//! - `maxLength`
49//!     - Maximum string length.
50//! - `pattern`
51//!     - Regular expression the string must match.
52//! - `format`
53//!     - Specifies a pre-defined format, these are supported [`FormatType`]
54//!
55//! #### Number
56//! - `minDigitsInteger`
57//!     - Specifies minimum number of digits in the integer part of a numeric value.
58//! - `maxDigitsInteger`
59//!     - Specifies maximum number of digits in the integer part of a numeric value.
60//! - `minDigitsFraction`
61//!     - Constraints on minimum number of digits allowed in the fractional part of a numeric value.
62//! - `maxDigitsFraction`
63//!     - Constraints on maximum number of digits allowed in the fractional part of a numeric value.
64//! - `minDigitsExponent`
65//!     - Defines minimum number of digits in the exponent part of a scientific notation number.
66//! - `maxDigitsExponent`
67//!     - Defines maximum number of digits in the exponent part of a scientific notation number.
68//!
69//! #### Integer
70//! - `minDigits`
71//!     - Defines the minimum number of digits.
72//! - `maxDigits`
73//!     - Defines the maximum number of digits.
74//!
75//! #### Logical
76//! - `allOf`
77//!     - Combines multiple schemas; all must be valid.
78//! - `anyOf`
79//!     - Combines multiple schemas; at least one must be valid.
80//! - `oneOf`
81//!     - Combines multiple schemas; exactly one must be valid.
82//!
83//! ### Recursion
84//!
85//! Currently maximum recursion depth is cautiously defined at the level 3.
86//!
87//! Note, that in general recursion in regular expressions is not the best approach due to inherent limitations
88//! and inefficiencies, especially when applied to complex patterns or large input.
89//!
90//! But often, even simple referential JSON schemas will produce enormous regex size, since it increases
91//! exponentially in recursive case, which likely to introduce performance issues by consuming large
92//! amounts of time, resources and memory.
93//!
94//! ### References
95//!
96//! Only local references are currently being supported.
97//!
98//! ### Unconstrained objects
99//!
100//! An empty object means unconstrained, allowing any JSON type.
101
102use serde_json::Value;
103pub use types::*;
104
105mod parsing;
106pub mod types;
107
108use crate::Result;
109
110/// Generates a regular expression string from given JSON schema string.
111///
112/// # Example
113///
114/// ```rust
115/// # use outlines_core::Error;
116/// use outlines_core::prelude::*;
117///
118/// # fn main() -> Result<(), Error> {
119///     // Define a JSON schema
120///     let schema = r#"{
121///         "type": "object",
122///         "properties": {
123///             "name": { "type": "string" },
124///             "age": { "type": "integer" }
125///         },
126///         "required": ["name", "age"]
127///     }"#;
128///
129///     // Generate regex from schema
130///     let regex = json_schema::regex_from_str(&schema, None)?;
131///     println!("Generated regex: {}", regex);
132///
133///     // Custom whitespace pattern could be passed as well
134///     let whitespace_pattern = Some(r#"[\n ]*"#);
135///     let regex = json_schema::regex_from_str(&schema, whitespace_pattern)?;
136///     println!("Generated regex with custom whitespace pattern: {}", regex);
137///
138/// #   Ok(())
139/// }
140/// ```
141pub fn regex_from_str(json: &str, whitespace_pattern: Option<&str>) -> Result<String> {
142    let json_value: Value = serde_json::from_str(json)?;
143    regex_from_value(&json_value, whitespace_pattern)
144}
145
146/// Generates a regular expression string from `serde_json::Value` type of JSON schema.
147///
148/// # Example
149///
150/// ```rust
151/// # use outlines_core::Error;
152/// use serde_json::Value;
153/// use outlines_core::prelude::*;
154///
155/// # fn main() -> Result<(), Error> {
156///     // Define a JSON schema
157///     let schema = r#"{
158///         "type": "object",
159///         "properties": {
160///             "name": { "type": "string" },
161///             "age": { "type": "integer" }
162///         },
163///         "required": ["name", "age"]
164///     }"#;
165///
166///     // If schema's `Value` was already parsed
167///     let schema_value: Value = serde_json::from_str(schema)?;
168///
169///     // It's possible to generate a regex from schema value
170///     let regex = json_schema::regex_from_value(&schema_value, None)?;
171///     println!("Generated regex: {}", regex);
172///
173///     // Custom whitespace pattern could be passed as well
174///     let whitespace_pattern = Some(r#"[\n ]*"#);
175///     let regex = json_schema::regex_from_value(&schema_value, whitespace_pattern)?;
176///     println!("Generated regex with custom whitespace pattern: {}", regex);
177///
178/// #   Ok(())
179/// }
180/// ```
181pub fn regex_from_value(json: &Value, whitespace_pattern: Option<&str>) -> Result<String> {
182    let mut parser = parsing::Parser::new(json);
183    if let Some(pattern) = whitespace_pattern {
184        parser = parser.with_whitespace_pattern(pattern)
185    }
186    parser.to_regex(json)
187}
188
189#[cfg(test)]
190mod tests {
191    use regex::Regex;
192
193    use super::*;
194
195    fn should_match(re: &Regex, value: &str) {
196        // Asserts that value is fully matched.
197        match re.find(value) {
198            Some(matched) => {
199                assert_eq!(
200                    matched.as_str(),
201                    value,
202                    "Value should match, but does not for: {value}, re:\n{re}"
203                );
204                assert_eq!(matched.range(), 0..value.len());
205            }
206            None => unreachable!(
207                "Value should match, but does not, in unreachable for: {value}, re:\n{re}"
208            ),
209        }
210    }
211
212    fn should_not_match(re: &Regex, value: &str) {
213        // Asserts that regex does not find a match or not a full match.
214        if let Some(matched) = re.find(value) {
215            assert_ne!(
216                matched.as_str(),
217                value,
218                "Value should NOT match, but does for: {value}, re:\n{re}"
219            );
220            assert_ne!(matched.range(), 0..value.len());
221        }
222    }
223
224    #[test]
225    fn test_schema_matches_regex() {
226        for (schema, regex, a_match, not_a_match) in [
227            // ==========================================================
228            //                       Integer Type
229            // ==========================================================
230            (
231                r#"{"title": "Foo", "type": "integer"}"#,
232                INTEGER,
233                vec!["0", "1", "-1"],
234                vec!["01", "1.3", "t"],
235            ),
236            // Required integer property
237            (
238                r#"{
239                    "title": "Foo",
240                    "type": "object",
241                    "properties": {"count": {"title": "Count", "type": "integer"}},
242                    "required": ["count"]
243                }"#,
244                r#"\{[ ]?"count"[ ]?:[ ]?(-)?(0|[1-9][0-9]*)[ ]?\}"#,
245                vec![r#"{ "count": 100 }"#],
246                vec![r#"{ "count": "a" }"#, ""],
247            ),
248            // Integer with minimum digits
249            (
250                r#"{
251                    "title": "Foo",
252                    "type": "object",
253                    "properties": {
254                        "count": {"title": "Count", "type": "integer", "minDigits": 3}
255                    },
256                    "required": ["count"]
257                }"#,
258                r#"\{[ ]?"count"[ ]?:[ ]?(-)?(0|[1-9][0-9]{2,})[ ]?\}"#,
259                vec![r#"{ "count": 100 }"#, r#"{ "count": 1000 }"#],
260                vec![r#"{ "count": 10 }"#],
261            ),
262            // Integer with maximum digits
263            (
264                r#"{
265                    "title": "Foo",
266                    "type": "object",
267                    "properties": {
268                        "count": {"title": "Count", "type": "integer", "maxDigits": 3}
269                    },
270                    "required": ["count"]
271                }"#,
272                r#"\{[ ]?"count"[ ]?:[ ]?(-)?(0|[1-9][0-9]{0,2})[ ]?\}"#,
273                vec![r#"{ "count": 100 }"#, r#"{ "count": 10 }"#],
274                vec![r#"{ "count": 1000 }"#],
275            ),
276            // Integer with minimum and maximum digits
277            (
278                r#"{
279                    "title": "Foo",
280                    "type": "object",
281                    "properties": {
282                        "count": {
283                            "title": "Count",
284                            "type": "integer",
285                            "minDigits": 3,
286                            "maxDigits": 5
287                        }
288                    },
289                    "required": ["count"]
290                }"#,
291                r#"\{[ ]?"count"[ ]?:[ ]?(-)?(0|[1-9][0-9]{2,4})[ ]?\}"#,
292                vec![r#"{ "count": 100 }"#, r#"{ "count": 10000 }"#],
293                vec![r#"{ "count": 10 }"#, r#"{ "count": 100000 }"#],
294            ),
295            // ==========================================================
296            //                       Number Type
297            // ==========================================================
298            (
299                r#"{"title": "Foo", "type": "number"}"#,
300                NUMBER,
301                vec!["1", "0", "1.3", "-1.3", "1.3e+9"],
302                vec!["01", ".3", "1.3e9"],
303            ),
304            // Required number property
305            (
306                r#"{
307                    "title": "Foo",
308                    "type": "object",
309                    "properties": {"count": {"title": "Count", "type": "number"}},
310                    "required": ["count"]
311                }"#,
312                r#"\{[ ]?"count"[ ]?:[ ]?((-)?(0|[1-9][0-9]*))(\.[0-9]+)?([eE][+-][0-9]+)?[ ]?\}"#,
313                vec![r#"{ "count": 100 }"#, r#"{ "count": 100.5 }"#],
314                vec![""],
315            ),
316            // Number with min and max integer digits
317            (
318                r#"{
319                    "title": "Foo",
320                    "type": "object",
321                    "properties": {
322                        "count": {
323                            "title": "Count",
324                            "type": "number",
325                            "minDigitsInteger": 3,
326                            "maxDigitsInteger": 5
327                        }
328                    },
329                    "required": ["count"]
330                }"#,
331                r#"\{[ ]?"count"[ ]?:[ ]?((-)?(0|[1-9][0-9]{2,4}))(\.[0-9]+)?([eE][+-][0-9]+)?[ ]?\}"#,
332                vec![r#"{ "count": 100.005 }"#, r#"{ "count": 10000.005 }"#],
333                vec![r#"{ "count": 10.005 }"#, r#"{ "count": 100000.005 }"#],
334            ),
335            // Number with min and max fraction digits
336            (
337                r#"{
338                    "title": "Foo",
339                    "type": "object",
340                    "properties": {
341                        "count": {
342                            "title": "Count",
343                            "type": "number",
344                            "minDigitsFraction": 3,
345                            "maxDigitsFraction": 5
346                        }
347                    },
348                    "required": ["count"]
349                }"#,
350                r#"\{[ ]?"count"[ ]?:[ ]?((-)?(0|[1-9][0-9]*))(\.[0-9]{3,5})?([eE][+-][0-9]+)?[ ]?\}"#,
351                vec![r#"{ "count": 1.005 }"#, r#"{ "count": 1.00005 }"#],
352                vec![r#"{ "count": 1.05 }"#, r#"{ "count": 1.000005 }"#],
353            ),
354            // Number with min and max exponent digits
355            (
356                r#"{
357                    "title": "Foo",
358                    "type": "object",
359                    "properties": {
360                        "count": {
361                            "title": "Count",
362                            "type": "number",
363                            "minDigitsExponent": 3,
364                            "maxDigitsExponent": 5
365                        }
366                    },
367                    "required": ["count"]
368                }"#,
369                r#"\{[ ]?"count"[ ]?:[ ]?((-)?(0|[1-9][0-9]*))(\.[0-9]+)?([eE][+-][0-9]{3,5})?[ ]?\}"#,
370                vec![r#"{ "count": 1.05e+001 }"#, r#"{ "count": 1.05e-00001 }"#],
371                vec![r#"{ "count": 1.05e1 }"#, r#"{ "count": 1.05e0000001 }"#],
372            ),
373            // Number with min and max integer, fraction and exponent digits
374            (
375                r#"{
376                    "title": "Foo",
377                    "type": "object",
378                    "properties": {
379                        "count": {
380                            "title": "Count",
381                            "type": "number",
382                            "minDigitsInteger": 3,
383                            "maxDigitsInteger": 5,
384                            "minDigitsFraction": 3,
385                            "maxDigitsFraction": 5,
386                            "minDigitsExponent": 3,
387                            "maxDigitsExponent": 5
388                        }
389                    },
390                    "required": ["count"]
391                }"#,
392                r#"\{[ ]?"count"[ ]?:[ ]?((-)?(0|[1-9][0-9]{2,4}))(\.[0-9]{3,5})?([eE][+-][0-9]{3,5})?[ ]?\}"#,
393                vec![r#"{ "count": 100.005e+001 }"#, r#"{ "count": 10000.00005e-00001 }"#],
394                vec![r#"{ "count": 1.05e1 }"#, r#"{ "count": 100000.0000005e0000001 }"#],
395            ),
396            // ==========================================================
397            //                       Array Type
398            // ==========================================================
399            (
400                r#"{"title": "Foo", "type": "array", "items": {"type": "number"}}"#,
401                format!(r#"\[{WHITESPACE}(({NUMBER})(,{WHITESPACE}({NUMBER})){{0,}})?{WHITESPACE}\]"#).as_str(),
402                vec!["[1e+9,1.3]", "[]"], vec!["[1", r#"["a"]"#],
403            ),
404            // Array with a set min length
405            (
406                r#"{
407                    "title": "Foo",
408                    "type": "array",
409                    "items": {"type": "integer"},
410                    "minItems": 3
411                }"#,
412                format!(r#"\[{WHITESPACE}(({INTEGER})(,{WHITESPACE}({INTEGER})){{2,}}){WHITESPACE}\]"#).as_str(),
413                vec!["[1,2,3]", "[1,2,3,4]"], vec!["[1]", "[1,2]", "[]"],
414            ),
415            // Array with a set max length
416            (
417                r#"{
418                    "title": "Foo",
419                    "type": "array",
420                    "items": {"type": "integer"},
421                    "maxItems": 3
422                }"#,
423                format!(r#"\[{WHITESPACE}(({INTEGER})(,{WHITESPACE}({INTEGER})){{0,2}})?{WHITESPACE}\]"#).as_str(),
424                vec!["[1,2,3]", "[1,2]", "[]"], vec!["[1,2,3,4]"],
425            ),
426            // Array with a set min/max length
427            (
428                r#"{
429                    "title": "Foo",
430                    "type": "array",
431                    "items": {"type": "integer"},
432                    "minItems": 1,
433                    "maxItems": 1
434                }"#,
435                format!(r#"\[{WHITESPACE}(({INTEGER})(,{WHITESPACE}({INTEGER})){{0,0}}){WHITESPACE}\]"#).as_str(),
436                vec!["[1]"], vec!["[1, 2]", r#"["a"]"#, "[]"],
437            ),
438            // Array with zero length
439            (
440                r#"{
441                    "title": "Foo",
442                    "type": "array",
443                    "items": {"type": "integer"},
444                    "minItems": 0,
445                    "maxItems": 0
446                }"#,
447                format!(r#"\[{WHITESPACE}\]"#).as_str(),
448                vec!["[]"], vec!["[1, 2]", "[1]", "[1,2,3,4]"],
449            ),
450            // ==========================================================
451            //                       String Type
452            // ==========================================================
453            (
454                r#"{"title": "Foo", "type": "string"}"#,
455                STRING,
456                vec![
457                    r#""(parenthesized_string)""#,
458                    r#""malformed) parenthesis (((() string""#,
459                    r#""quoted_string""#,
460                    r#""double_\\escape""#,
461                    r#""\\n""#,
462                    r#""escaped \" quote""#,
463                ],
464                vec![
465                    "unquotedstring",
466                    r#""escape_\character""#,
467                    r#""\n""#,
468                    r#""unescaped " quote""#,
469                ],
470            ),
471            (
472                r#"{"title": "Foo", "type": "boolean"}"#,
473                BOOLEAN,
474                vec!["true", "false"],
475                vec!["null", "0"],
476            ),
477            (
478                r#"{"title": "Foo", "type": "null"}"#,
479                NULL,
480                vec!["null"],
481                vec!["true", "0"],
482            ),
483            // String with maximum length
484            (
485                r#"{"title": "Foo", "type": "string", "maxLength": 3}"#,
486                format!(r#""{STRING_INNER}{{0,3}}""#).as_str(),
487                vec![r#""ab""#], vec![r#""a"""#, r#""abcd""#],
488            ),
489            // String with minimum length
490            (
491                r#"{"title": "Foo", "type": "string", "minLength": 3}"#,
492                format!(r#""{STRING_INNER}{{3,}}""#).as_str(),
493                vec![r#""abcd""#], vec![r#""ab""#, r#""abc"""#],
494            ),
495            // String with both minimum and maximum length
496            (
497                r#"{"title": "Foo", "type": "string", "minLength": 3, "maxLength": 5}"#,
498                format!(r#""{STRING_INNER}{{3,5}}""#).as_str(),
499                vec![r#""abcd""#], vec![r#""ab""#, r#""abcdef"""#],
500            ),
501            // String defined by a regular expression
502            (
503                r#"{"title": "Foo", "type": "string", "pattern": "^[a-z]$"}"#,
504                r#"("[a-z]")"#,
505                vec![r#""a""#], vec![r#""1""#],
506            ),
507            // Make sure strings are escaped with regex escaping
508            (
509                r#"{"title": "Foo", "const": ".*", "type": "string"}"#,
510                r#""\.\*""#,
511                vec![r#"".*""#], vec![r#""\s*""#, r#""\.\*""#],
512            ),
513            // Make sure strings are escaped with JSON escaping
514            (
515                r#"{"title": "Foo", "const": "\"", "type": "string"}"#,
516                r#""\\"""#,
517                vec![r#""\"""#], vec![r#"""""#],
518            ),
519            // ==========================================================
520            //                       Const
521            // ==========================================================
522            // Const string
523            (
524                r#"{"title": "Foo", "const": "Marc", "type": "string"}"#,
525                r#""Marc""#,
526                vec![r#""Marc""#], vec![r#""Jonh""#, r#""Mar""#],
527            ),
528            // Const integer
529            (
530                r#"{"title": "Foo", "const": 0, "type": "integer"}"#,
531                "0",
532                vec!["0"], vec!["1", "a"],
533            ),
534            // Const float
535            (
536                r#"{"title": "Foo", "const": 0.2, "type": "float"}"#,
537                r#"0\.2"#,
538                vec!["0.2"], vec!["032"],
539            ),
540            // Const boolean
541            (
542                r#"{"title": "Foo", "const": true, "type": "boolean"}"#,
543                "true",
544                vec!["true"], vec!["false", "null"],
545            ),
546            // Const null
547            (
548                r#"{"title": "Foo", "const": null, "type": "null"}"#,
549                "null",
550                vec!["null"], vec!["none", ""],
551            ),
552            // ==========================================================
553            //                      Enum
554            // ==========================================================
555            (
556                r#"{"title": "Foo", "enum": ["Marc", "Jean"], "type": "string"}"#,
557                r#"("Marc"|"Jean")"#,
558                vec![r#""Marc""#, r#""Jean""#], vec![r#""Jonh""#],
559            ),
560            // Enum with regex and JSON escaping
561            (
562                r#"{"title": "Foo", "enum": [".*", "\\s*"], "type": "string"}"#,
563                r#"("\.\*"|"\\\\s\*")"#,
564                vec![r#"".*""#, r#""\\s*""#], vec![r#""\.\*""#],
565            ),
566            // Enum integer
567            (
568                r#"{"title": "Foo", "enum": [0, 1], "type": "integer"}"#,
569                r#"(0|1)"#,
570                vec!["0", "1"], vec!["a"],
571            ),
572            // Enum mix of types
573            (
574                r#"{"title": "Foo", "enum": [6, 5.3, "potato", true, null]}"#,
575                r#"(6|5\.3|"potato"|true|null)"#,
576                vec!["6", "5.3", r#""potato""#, "true", "null"], vec!["none", "53"],
577            ),
578            // ==========================================================
579            //                      UUID
580            // ==========================================================
581            (
582                r#"{"title": "Foo", "type": "string", "format": "uuid"}"#,
583                UUID,
584                vec![
585                    r#""123e4567-e89b-12d3-a456-426614174000""#,
586                ],
587                vec![
588                    r#"123e4567-e89b-12d3-a456-426614174000"#,
589                    r#""123e4567-e89b-12d3-a456-42661417400""#,
590                    r#""123e4567-e89b-12d3-a456-42661417400g""#,
591                    r#""123e4567-e89b-12d3-a456-42661417400-""#,
592                    r#""""#,
593                ],
594            ),
595            // Nested UUID
596            (
597                r#"{
598                    "title": "Foo",
599                    "type": "object",
600                    "properties": {"uuid": {"type": "string", "format": "uuid"}}
601                }"#,
602                format!(r#"\{{([ ]?"uuid"[ ]?:[ ]?{UUID})?[ ]?\}}"#).as_str(),
603                vec![
604                    r#"{"uuid": "123e4567-e89b-12d3-a456-426614174000"}"#,
605                ],
606                vec![
607                    r#"{"uuid":"123e4567-e89b-12d3-a456-42661417400"}"#,
608                    r#"{"uuid":"123e4567-e89b-12d3-a456-42661417400g"}"#,
609                    r#"{"uuid":"123e4567-e89b-12d3-a456-42661417400-"}"#,
610                    r#"{"uuid":123e4567-e89b-12d3-a456-426614174000}"#, // missing quotes for value
611                    r#"{"uuid":""}"#,
612                ],
613            ),
614            // ==========================================================
615            //                     DATE & TIME
616            // ==========================================================
617            // DATE-TIME
618            (
619                r#"{"title": "Foo", "type": "string", "format": "date-time"}"#,
620                DATE_TIME,
621                vec![
622                    r#""2018-11-13T20:20:39Z""#,
623                    r#""2016-09-18T17:34:02.666Z""#,
624                    r#""2008-05-11T15:30:00Z""#,
625                    r#""2021-01-01T00:00:00""#,
626                ],
627                vec![
628                    "2018-11-13T20:20:39Z",
629                    r#""2022-01-10 07:19:30""#, // missing T
630                    r#""2022-12-10T10-04-29""#, // incorrect separator
631                    r#""2023-01-01""#,
632                ],
633            ),
634            // DATE
635            (
636                r#"{"title": "Foo", "type": "string", "format": "date"}"#,
637                DATE,
638                vec![
639                    r#""2018-11-13""#,
640                    r#""2016-09-18""#,
641                    r#""2008-05-11""#,
642                ],
643                vec![
644                    "2018-11-13",
645                    r#""2015-13-01""#, // incorrect month
646                    r#""2022-01""#, // missing day
647                    r#""2022/12/01""#, // incorrect separator
648                ],
649            ),
650            // TIME
651            (
652                r#"{"title": "Foo", "type": "string", "format": "time"}"#,
653                TIME,
654                vec![
655                    r#""20:20:39Z""#,
656                    r#""15:30:00Z""#,
657                ],
658                vec![
659                    "20:20:39Z",
660                    r#""25:30:00""#, // incorrect hour
661                    r#""15:30""#, // missing seconds
662                    r#""15:30:00.000""#, // missing Z
663                    r#""15-30-00""#, // incorrect separator
664                    r#""15:30:00+01:00""#, // incorrect separator
665                ],
666            ),
667            // Nested DATE-TIME
668            (
669                r#"{
670                    "title": "Foo",
671                    "type": "object",
672                    "properties": {"dateTime": {"type": "string", "format": "date-time"}}
673                }"#,
674                format!(r#"\{{([ ]?"dateTime"[ ]?:[ ]?{DATE_TIME})?[ ]?\}}"#).as_str(),
675                vec![
676                    r#"{"dateTime": "2018-11-13T20:20:39Z"}"#,
677                    r#"{"dateTime":"2016-09-18T17:34:02.666Z"}"#,
678                    r#"{"dateTime":"2008-05-11T15:30:00Z"}"#,
679                    r#"{"dateTime":"2021-01-01T00:00:00"}"#,
680                ],
681                vec![
682                    r#"{"dateTime":"2022-01-10 07:19:30"}"#, // missing T
683                    r#"{"dateTime":"2022-12-10T10-04-29"}"#, // incorrect separator
684                    r#"{"dateTime":2018-11-13T20:20:39Z}"#, // missing quotes for value
685                    r#"{"dateTime":"2023-01-01"}"#,
686                ],
687            ),
688            // Nested DATE
689            (
690                r#"{
691                    "title": "Foo",
692                    "type": "object",
693                    "properties": {"date": {"type": "string", "format": "date"}}
694                }"#,
695                format!(r#"\{{([ ]?"date"[ ]?:[ ]?{DATE})?[ ]?\}}"#).as_str(),
696                vec![
697                    r#"{"date": "2018-11-13"}"#,
698                    r#"{"date":"2016-09-18"}"#,
699                    r#"{"date":"2008-05-11"}"#,
700                ],
701                vec![
702                    r#"{"date":"2015-13-01"}"#, // incorrect month
703                    r#"{"date":"2022-01"}"#, // missing day
704                    r#"{"date":"2022/12/01"}"#, // incorrect separator
705                    r#"{"date":2018-11-13}"#, // missing quotes for value
706                ],
707            ),
708            // Nested TIME
709            (
710                r#"{
711                    "title": "Foo",
712                    "type": "object",
713                    "properties": {"time": {"type": "string", "format": "time"}}
714                }"#,
715                format!(r#"\{{([ ]?"time"[ ]?:[ ]?{TIME})?[ ]?\}}"#).as_str(),
716                vec![
717                    r#"{"time": "20:20:39Z"}"#,
718                    r#"{"time":"15:30:00Z"}"#,
719                ],
720                vec![
721                    r#"{"time":"25:30:00"}"#, // incorrect hour
722                    r#"{"time":"15:30"}"#, // missing seconds
723                    r#"{"time":"15:30:00.000"}"#, // missing Z
724                    r#"{"time":"15-30-00"}"#, // incorrect separator
725                    r#"{"time":"15:30:00+01:00"}"#, // incorrect separator
726                    r#"{"time":20:20:39Z}"#, // missing quotes for value
727                ],
728            ),
729            // ==========================================================
730            //                     ... Of
731            // ==========================================================
732            // oneOf
733            (
734                r#"{
735                    "title": "Foo",
736                    "oneOf": [{"type": "string"}, {"type": "number"}, {"type": "boolean"}]
737                }"#,
738                format!(r#"((?:"{STRING_INNER}*")|(?:{NUMBER})|(?:{BOOLEAN}))"#).as_str(),
739                vec!["12.3", "true", r#""a""#],
740                vec![
741                    "null",
742                    "",
743                    "12true",
744                    r#"1.3"a""#,
745                    r#"12.3true"a""#,
746                ],
747            ),
748            // anyOf
749            (
750                r#"{
751                    "title": "Foo",
752                    "anyOf": [{"type": "string"}, {"type": "integer"}]
753                }"#,
754                format!(r#"({STRING}|{INTEGER})"#).as_str(),
755                vec!["12", r#""a""#],
756                vec![r#"1"a""#],
757            ),
758            // allOf
759            (
760                r#"{
761                    "title": "Foo",
762                    "allOf": [{"type": "string"}, {"type": "integer"}]
763                }"#,
764                format!(r#"({STRING}{INTEGER})"#).as_str(),
765                vec![r#""a"1"#],
766                vec![r#""a""#, r#""1""#],
767            ),
768            // ==========================================================
769            //                     Object
770            // ==========================================================
771            (
772                r#"{
773                    "title": "TestSchema",
774                    "type": "object",
775                    "properties": {
776                        "test_dict": {
777                            "title": "Test Dict",
778                            "additionalProperties": {"type": "string"},
779                            "type": "object"
780                        }
781                    },
782                    "required": ["test_dict"]
783                }"#,
784                format!(r#"\{{{WHITESPACE}"test_dict"{WHITESPACE}:{WHITESPACE}\{{{WHITESPACE}({STRING}{WHITESPACE}:{WHITESPACE}{STRING}({WHITESPACE},{WHITESPACE}{STRING}{WHITESPACE}:{WHITESPACE}{STRING}){{0,}})?{WHITESPACE}\}}{WHITESPACE}\}}"#).as_str(),
785                vec![
786                    r#"{ "test_dict":{"foo":"bar","baz": "bif"}}"#,
787                    r#"{ "test_dict":{"foo":"bar" }}"#,
788                    r#"{ "test_dict":{}}"#,
789                ],
790                vec![
791                    r#"{ "WRONG_KEY":{}}"#,
792                    r#"{ "test_dict":{"wrong_type" 1}}"#,
793                ],
794            ),
795            // Object containing object with undefined keys
796            (
797                r#"{
798                    "title": "TestSchema",
799                    "type": "object",
800                    "properties": {
801                        "test_dict": {
802                            "title": "Test Dict",
803                            "additionalProperties": {
804                                "additionalProperties": {"type": "integer"},
805                                "type": "object"
806                            },
807                            "type": "object"
808                        }
809                    },
810                    "required": ["test_dict"]
811                }"#,
812                format!(r#"\{{{WHITESPACE}"test_dict"{WHITESPACE}:{WHITESPACE}\{{{WHITESPACE}({STRING}{WHITESPACE}:{WHITESPACE}\{{{WHITESPACE}({STRING}{WHITESPACE}:{WHITESPACE}{INTEGER}({WHITESPACE},{WHITESPACE}{STRING}{WHITESPACE}:{WHITESPACE}{INTEGER}){{0,}})?{WHITESPACE}\}}({WHITESPACE},{WHITESPACE}{STRING}{WHITESPACE}:{WHITESPACE}\{{{WHITESPACE}({STRING}{WHITESPACE}:{WHITESPACE}{INTEGER}({WHITESPACE},{WHITESPACE}{STRING}{WHITESPACE}:{WHITESPACE}{INTEGER}){{0,}})?{WHITESPACE}\}}){{0,}})?{WHITESPACE}\}}{WHITESPACE}\}}"#).as_str(),
813                vec![
814                    r#"{"test_dict": {"foo": {"bar": 123, "apple": 99}, "baz": {"bif": 456}}}"#,
815                    r#"{"test_dict": {"anykey": {"anykey": 123}, "anykey2": {"bif": 456}}}"#,
816                    r#"{"test_dict": {}}"#,
817                    r#"{"test_dict": {"dict of empty dicts are ok": {} }}"#,
818                ],
819                vec![
820                    r#"{"test_dict": {"anykey": {"ONLY Dict[Dict]": 123}, "No Dict[int]" 1: }}"#,
821                    r#"{"test_dict": {"anykey": {"anykey": 123}, "anykey2": {"bif": "bof"}}}"#,
822                ],
823            ),
824            // Object contains object with defined keys
825            (
826                r#"{
827                    "title": "Bar",
828                    "type": "object",
829                    "properties": {
830                        "fuzz": {
831                            "title": "Foo",
832                            "type": "object",
833                            "properties": {"spam": {"title": "Spam", "type": "integer"}},
834                            "required": ["spam"]
835                        }
836                    },
837                    "required": ["fuzz"]
838                }"#,
839                format!(r#"\{{[ ]?"fuzz"[ ]?:[ ]?\{{[ ]?"spam"[ ]?:[ ]?{INTEGER}[ ]?\}}[ ]?\}}"#).as_str(),
840                vec![r#"{ "fuzz": { "spam": 100 }}"#],
841                vec![r#"{ "fuzz": { "spam": 100, "notspam": 500 }}"#, r#"{ "fuzz": {}}"#, r#"{ "spam": 5}"#],
842            ),
843            // Object with internal reference: #/
844            (
845                r##"{
846                    "title": "User",
847                    "type": "object",
848                    "properties": {
849                        "user_id": {"title": "User Id", "type": "integer"},
850                        "name": {"title": "Name", "type": "string"},
851                        "a": {"$ref": "#/properties/name"}
852                    },
853                    "required": ["user_id", "name", "a"]
854                }"##,
855                format!(r#"\{{[ ]?"user_id"[ ]?:[ ]?{INTEGER}[ ]?,[ ]?"name"[ ]?:[ ]?{STRING}[ ]?,[ ]?"a"[ ]?:[ ]?{STRING}[ ]?\}}"#).as_str(),
856                vec![r#"{"user_id": 100, "name": "John", "a": "Marc"}"#],
857                vec![r#"{"user_id": 100, "name": "John", "a": 0}"#],
858            ),
859            // Object with internal reference: #/$defs
860            (
861                r##"{
862                    "title": "User",
863                    "type": "object",
864                    "$defs": {"name": {"title": "Name2", "type": "string"}},
865                    "properties": {
866                        "user_id": {"title": "User Id", "type": "integer"},
867                        "name": {"title": "Name", "type": "string"},
868                        "name2": {"$ref": "#/$defs/name"}
869                    },
870                    "required": ["user_id", "name", "name2"]
871                }"##,
872                format!(r#"\{{[ ]?"user_id"[ ]?:[ ]?{INTEGER}[ ]?,[ ]?"name"[ ]?:[ ]?{STRING}[ ]?,[ ]?"name2"[ ]?:[ ]?{STRING}[ ]?\}}"#).as_str(),
873                vec![r#"{"user_id": 100, "name": "John", "name2": "Marc"}"#],
874                vec![r#"{"user_id": 100, "name": "John", "name2": 0}"#],
875            ),
876            // Object with internal reference to $id: $id#/$defs
877            // And required list requires more than being defined
878            (
879                r##"{
880                    "$id": "customer",
881                    "$schema": "https://json-schema.org/draft/2020-12/schema",
882                    "title": "Customer",
883                    "type": "object",
884                    "properties": {
885                        "name": {"type": "string"},
886                        "last_name": {"type": "string"},
887                        "address": {"$ref": "customer#/$defs/address"}
888                    },
889                    "required": [
890                        "name",
891                        "first_name",
892                        "last_name",
893                        "address",
894                        "shipping_address",
895                        "billing_address"
896                    ],
897                    "$defs": {
898                        "address": {
899                            "title": "Address",
900                            "$schema": "http://json-schema.org/draft-07/schema#",
901                            "type": "object",
902                            "properties": {
903                                "city": {"type": "string"}
904                            },
905                            "required": ["street_address", "city", "state"],
906                            "definitions": {
907                                "state": {
908                                    "type": "object",
909                                    "title": "State",
910                                    "properties": {"name": {"type": "string"}},
911                                    "required": ["name"]
912                                }
913                            }
914                        }
915                    }
916                }"##,
917                format!(r#"\{{[ ]?"name"[ ]?:[ ]?{STRING}[ ]?,[ ]?"last_name"[ ]?:[ ]?{STRING}[ ]?,[ ]?"address"[ ]?:[ ]?\{{[ ]?"city"[ ]?:[ ]?{STRING}[ ]?\}}[ ]?\}}"#).as_str(),
918                vec![
919                    r#"{"name": "John", "last_name": "Doe", "address": {"city": "Paris"}}"#,
920                ],
921                vec![
922                    r#"{"name": "John", "last_name": "Doe", "address": {}}"#,
923                    r#"{"name": "John", "last_name": "Doe"}"#,
924                ],
925            ),
926            // Object with optional properties:
927            // - last required property in first position
928            (
929                r#"{
930                    "properties": {
931                        "name": {"type": "string"},
932                        "age": {"anyOf": [{"type": "integer"}, {"type": "null"}]},
933                        "weapon": {"anyOf": [{"type": "string"}, {"type": "null"}]}
934                    },
935                    "required": ["name"],
936                    "title": "Character",
937                    "type": "object"
938                }"#,
939                format!(r#"\{{[ ]?"name"[ ]?:[ ]?{STRING}([ ]?,[ ]?"age"[ ]?:[ ]?({INTEGER}|null))?([ ]?,[ ]?"weapon"[ ]?:[ ]?({STRING}|null))?[ ]?\}}"#).as_str(),
940                vec![
941                    r#"{ "name" : "Player" }"#,
942                    r#"{ "name" : "Player", "weapon" : "sword" }"#,
943                ],
944                vec![
945                    r#"{ "age" : 10, "weapon" : "sword" }"#,
946                ],
947            ),
948            // Object with optional properties:
949            // - last required property in middle position
950            (
951                r#"{
952                    "properties": {
953                        "name": {"type": "string"},
954                        "age": {"anyOf": [{"type": "integer"}, {"type": "null"}]},
955                        "weapon": {"type": "string"},
956                        "strength": {"anyOf": [{"type": "integer"}, {"type": "null"}]}
957                    },
958                    "required": ["name", "weapon"],
959                    "title": "Character",
960                    "type": "object"
961                }"#,
962                format!(r#"\{{[ ]?"name"[ ]?:[ ]?{STRING}[ ]?,([ ]?"age"[ ]?:[ ]?({INTEGER}|null)[ ]?,)?[ ]?"weapon"[ ]?:[ ]?{STRING}([ ]?,[ ]?"strength"[ ]?:[ ]?({INTEGER}|null))?[ ]?\}}"#).as_str(),
963                vec![
964                    r#"{ "name" : "Player" , "weapon" : "sword" }"#,
965                    r#"{ "name" : "Player", "age" : 10, "weapon" : "sword" , "strength" : 10 }"#,
966                ],
967                vec![
968                    r#"{ "weapon" : "sword" }"#,
969                ],
970            ),
971            // Object with optional properties:
972            // - last required property in last position
973            (
974                r#"{
975                    "properties": {
976                        "name": {"anyOf": [{"type": "string"}, {"type": "null"}]},
977                        "age": {"type": "integer"},
978                        "armor": {"type": "string"},
979                        "strength": {"anyOf": [{"type": "integer"}, {"type": "null"}]},
980                        "weapon": {"title": "Weapon", "type": "string"}
981                    },
982                    "required": ["age", "armor", "weapon"],
983                    "title": "Character",
984                    "type": "object"
985                }"#,
986                format!(r#"\{{([ ]?"name"[ ]?:[ ]?({STRING}|null)[ ]?,)?[ ]?"age"[ ]?:[ ]?{INTEGER}[ ]?,[ ]?"armor"[ ]?:[ ]?{STRING}[ ]?,([ ]?"strength"[ ]?:[ ]?({INTEGER}|null)[ ]?,)?[ ]?"weapon"[ ]?:[ ]?{STRING}[ ]?\}}"#).as_str(),
987                vec![
988                    r#"{ "name" : "Player", "age" : 10, "armor" : "plate", "strength" : 11, "weapon" : "sword" }"#,
989                    r#"{ "age" : 10, "armor" : "plate", "weapon" : "sword" }"#,
990                ],
991                vec![
992                    r#"{ "name" : "Kahlhanbeh", "armor" : "plate", "weapon" : "sword" }"#,
993                ],
994            ),
995            // Object with all optional properties
996            (
997                r#"{
998                    "properties": {
999                        "name": {"anyOf": [{"type": "string"}, {"type": "null"}]},
1000                        "age": {"anyOf": [{"type": "integer"}, {"type": "null"}]},
1001                        "strength": {"anyOf": [{"type": "integer"}, {"type": "null"}]}
1002                    },
1003                    "title": "Character",
1004                    "type": "object"
1005                }"#,
1006                format!(r#"\{{([ ]?"name"[ ]?:[ ]?({STRING}|null)|([ ]?"name"[ ]?:[ ]?({STRING}|null)[ ]?,)?[ ]?"age"[ ]?:[ ]?({INTEGER}|null)|([ ]?"name"[ ]?:[ ]?({STRING}|null)[ ]?,)?([ ]?"age"[ ]?:[ ]?({INTEGER}|null)[ ]?,)?[ ]?"strength"[ ]?:[ ]?({INTEGER}|null))?[ ]?\}}"#).as_str(),
1007                vec![
1008                    r#"{ "name" : "Player" }"#,
1009                    r#"{ "name" : "Player", "age" : 10, "strength" : 10 }"#,
1010                    r#"{ "age" : 10, "strength" : 10 }"#,
1011                    "{ }",
1012                ],
1013                vec![r#"{ "foo": 0 } "#],
1014            ),
1015            // ==========================================================
1016            //                    Misc
1017            // ==========================================================
1018            // prefixItems
1019            (
1020                r#"{
1021                    "title": "Foo",
1022                    "prefixItems": [{"type": "string"}, {"type": "integer"}]
1023                }"#,
1024                format!(r#"\[{WHITESPACE}{STRING}{WHITESPACE},{WHITESPACE}{INTEGER}{WHITESPACE}\]"#).as_str(),
1025                vec![r#"["a", 1]"#],
1026                vec![r#"["a", 1, 1]"#, "[]"],
1027            ),
1028            // Unconstrained value (no schema)
1029            // (huge regex, but important test to verify matching it explicitely)
1030            (
1031                "{}",
1032                "((true|false))|(null)|(((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?)|((-)?(0|[1-9][0-9]*))|(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")|(\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])){0,})?[ ]?\\])(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])){0,})?[ ]?\\])){0,})?[ ]?\\])|(\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])){0,})?[ ]?\\])([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|\\{[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)([ ]?,[ ]?\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"[ ]?:[ ]?(\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\"|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(true|false)|null)){0,})?[ ]?\\}|\\[[ ]?(((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")(,[ ]?((true|false)|null|((-)?(0|[1-9][0-9]*))(\\.[0-9]+)?([eE][+-][0-9]+)?|(-)?(0|[1-9][0-9]*)|\"([^\"\\\\\\x00-\\x1F\\x7F-\\x9F]|\\\\[\"\\\\])*\")){0,})?[ ]?\\])){0,})?[ ]?\\])){0,})?[ ]?\\})",
1033                vec![
1034                    r#""aaabbuecuh""#,
1035                    "5.554",
1036                    "true",
1037                    "null",
1038                    "5999",
1039                    r#"["a", "b"]"#,
1040                    r#"{"key": {"k2": "value"}}"#,
1041                ],
1042                vec!["this isnt valid json"],
1043            ),
1044            // ==========================================================
1045            //                      URI Format
1046            // ==========================================================
1047            (
1048                r#"{"title": "Foo", "type": "string", "format": "uri"}"#,
1049                URI,
1050                vec![
1051                    "http://example.com",
1052                    "https://example.com/path?query=param#fragment",
1053                    "ftp://ftp.example.com/resource",
1054                    "urn:isbn:0451450523",
1055                ],
1056                vec![
1057                    "http:/example.com", // missing slash
1058                    "htp://example.com", // invalid scheme
1059                    "http://",           // missing host
1060                    "example.com",       // missing scheme
1061                ]
1062            ),
1063            (
1064                r#"{"title": "Bar", "type": "string", "format": "email"}"#,
1065                EMAIL,
1066                vec![
1067                    // Valid emails
1068                    "user@example.com",               // valid
1069                    "user.name+tag+sorting@example.com", // valid
1070                    "user_name@example.co.uk",         // valid
1071                    "user-name@sub.example.com",       // valid
1072                ],
1073                vec![
1074                    // Invalid emails
1075                    "plainaddress",                   // missing '@' and domain
1076                    "@missingusername.com",           // missing username
1077                    "username@.com",                  // leading dot in domain
1078                    "username@com",                   // TLD must have at least 2 characters
1079                    "username@example,com",           // invalid character in domain
1080                    "username@.example.com",          // leading dot in domain
1081                    "username@-example.com",          // domain cannot start with a hyphen
1082                    "username@example-.com",          // domain cannot end with a hyphen
1083                    "username@example..com",          // double dot in domain name
1084                    "username@.example..com",         // multiple errors in domain
1085                ]
1086            ),
1087
1088            // ==========================================================
1089            //                      Multiple types
1090            // ==========================================================
1091            (
1092                r#"{
1093                    "title": "Foo",
1094                    "type": ["string", "number", "boolean"]
1095                }"#,
1096                format!(r#"((?:"{STRING_INNER}*")|(?:{NUMBER})|(?:{BOOLEAN}))"#).as_str(),
1097                vec!["12.3", "true", r#""a""#],
1098                vec![
1099                    "null",
1100                    "",
1101                    "12true",
1102                    r#"1.3"a""#,
1103                    r#"12.3true"a""#,
1104                ],
1105            ),
1106            // Confirm that oneOf doesn't produce illegal lookaround: https://github.com/dottxt-ai/outlines/issues/823
1107            //
1108            // The pet field uses the discriminator field to decide which schema (Cat or Dog) applies, based on the pet_type property.
1109            // - if pet_type is "cat", the Cat schema applies, requiring a meows field (integer)
1110            // - if pet_type is "dog", the Dog schema applies, requiring a barks field (number)
1111            //
1112            // So, expected object requires two fields:
1113            //  - pet, which must be one of two types: Cat or Dog, determined by the pet_type field
1114            //  - n, an integer
1115            (
1116                r##"{
1117                    "$defs": {
1118                        "Cat": {
1119                            "properties": {
1120                                "pet_type": {
1121                                    "const": "cat",
1122                                    "enum": ["cat"],
1123                                    "title": "Pet Type",
1124                                    "type": "string"
1125                                },
1126                                "meows": {
1127                                    "title": "Meows",
1128                                    "type": "integer"
1129                                }
1130                            },
1131                            "required": ["pet_type", "meows"],
1132                            "title": "Cat",
1133                            "type": "object"
1134                        },
1135                        "Dog": {
1136                            "properties": {
1137                                "pet_type": {
1138                                    "const": "dog",
1139                                    "enum": ["dog"],
1140                                    "title": "Pet Type",
1141                                    "type": "string"
1142                                },
1143                                "barks": {
1144                                    "title": "Barks",
1145                                    "type": "number"
1146                                }
1147                            },
1148                            "required": ["pet_type", "barks"],
1149                            "title": "Dog",
1150                            "type": "object"
1151                        }
1152                    },
1153                    "properties": {
1154                        "pet": {
1155                            "discriminator": {
1156                                "mapping": {
1157                                    "cat": "#/$defs/Cat",
1158                                    "dog": "#/$defs/Dog"
1159                                },
1160                                "propertyName": "pet_type"
1161                            },
1162                            "oneOf": [
1163                                {"$ref": "#/$defs/Cat"},
1164                                {"$ref": "#/$defs/Dog"}
1165                            ],
1166                            "title": "Pet"
1167                        },
1168                        "n": {
1169                            "title": "N",
1170                            "type": "integer"
1171                        }
1172                    },
1173                    "required": ["pet", "n"],
1174                    "title": "Model",
1175                    "type": "object"
1176                }"##,
1177                r#"\{[ ]?"pet"[ ]?:[ ]?((?:\{[ ]?"pet_type"[ ]?:[ ]?("cat")[ ]?,[ ]?"meows"[ ]?:[ ]?(-)?(0|[1-9][0-9]*)[ ]?\})|(?:\{[ ]?"pet_type"[ ]?:[ ]?("dog")[ ]?,[ ]?"barks"[ ]?:[ ]?((-)?(0|[1-9][0-9]*))(\.[0-9]+)?([eE][+-][0-9]+)?[ ]?\}))[ ]?,[ ]?"n"[ ]?:[ ]?(-)?(0|[1-9][0-9]*)[ ]?\}"#,
1178                vec![
1179                    r#"{ "pet": { "pet_type": "cat", "meows": 5 }, "n": 10 }"#,
1180                    r#"{ "pet": { "pet_type": "dog", "barks": 3.5 }, "n": 7 }"#,
1181                ],
1182                vec![
1183                    // Missing required fields
1184                    r#"{ "pet": { "pet_type": "cat" }, "n": 10 }"#,
1185                    // Incorrect pet_type
1186                    r#"{ "pet": { "pet_type": "bird", "meows": 2 }, "n": 5 }"#
1187                ],
1188            ),
1189        ] {
1190            let result = regex_from_str(schema, None).expect("To regex failed");
1191            assert_eq!(result, regex, "JSON Schema {} didn't match", schema);
1192
1193            let re = Regex::new(&result).expect("Regex failed");
1194            for m in a_match {
1195                should_match(&re, m);
1196            }
1197            for not_m in not_a_match {
1198                should_not_match(&re, not_m);
1199            }
1200        }
1201    }
1202
1203    #[test]
1204    fn test_unconstrained_others() {
1205        for (schema, a_match, not_a_match) in [
1206            // Unconstrained Object
1207            (
1208                r#"{
1209                    "title": "Foo",
1210                    "type": "object"
1211                }"#,
1212                vec![
1213                    "{}",
1214                    r#"{"a": 1, "b": null}"#,
1215                    r#"{"a": {"z": {"g": 4}}, "b": null}"#,
1216                ],
1217                vec![
1218                    "1234",          // not an object
1219                    r#"["a", "a"]"#, // not an array
1220                ],
1221            ),
1222            // Unconstrained Array
1223            (
1224                r#"{"type": "array"}"#,
1225                vec![
1226                    r#"[1, {}, false]"#,
1227                    r#"[{}]"#,
1228                    r#"[{"a": {"z": "q"}, "b": null}]"#,
1229                    r#"[{"a": [1, 2, true], "b": null}]"#,
1230                    r#"[{"a": [1, 2, true], "b": {"a": "b"}}, 1, true, [1, [2]]]"#,
1231                ],
1232                vec![
1233                    // too deep, default unconstrained depth limit = 2
1234                    r#"[{"a": [1, 2, true], "b": {"a": "b"}}, 1, true, [1, [2, [3]]]]"#,
1235                    r#"[{"a": {"z": {"g": 4}}, "b": null}]"#,
1236                    r#"[[[[1]]]]"#,
1237                    // not an array
1238                    r#"{}"#,
1239                    r#"{"a": 1, "b": null}"#,
1240                    r#"{"a": {"z": {"g": 4}}, "b": null}"#,
1241                    "1234",
1242                    r#"{"a": "a"}"#,
1243                ],
1244            ),
1245        ] {
1246            let regex = regex_from_str(schema, None).expect("To regex failed");
1247            let re = Regex::new(&regex).expect("Regex failed");
1248            for m in a_match {
1249                should_match(&re, m);
1250            }
1251            for not_m in not_a_match {
1252                should_not_match(&re, not_m);
1253            }
1254        }
1255    }
1256
1257    #[test]
1258    fn with_whitespace_patterns() {
1259        let schema = r#"{
1260            "title": "Foo",
1261            "type": "object",
1262            "properties": {"date": {"type": "string", "format": "date"}}
1263        }"#;
1264
1265        for (whitespace_pattern, expected_regex, a_match) in [
1266            // Default
1267            (
1268                None,
1269                format!(
1270                    r#"\{{({WHITESPACE}"date"{WHITESPACE}:{WHITESPACE}{DATE})?{WHITESPACE}\}}"#
1271                ),
1272                vec![
1273                    r#"{"date": "2018-11-13"}"#,
1274                    r#"{ "date": "2018-11-13"}"#,
1275                    r#"{"date": "2018-11-13" }"#,
1276                ],
1277            ),
1278            (
1279                Some(r#"[\n ]*"#),
1280                format!(
1281                    r#"\{{({ws}"date"{ws}:{ws}{DATE})?{ws}\}}"#,
1282                    ws = r#"[\n ]*"#
1283                ),
1284                vec![
1285                    r#"{
1286                        "date":  "2018-11-13"
1287                    }"#,
1288                    r#"{ "date":
1289
1290                    "2018-11-13"     }"#,
1291                ],
1292            ),
1293            (
1294                Some("SPACE"),
1295                format!(r#"\{{({ws}"date"{ws}:{ws}{DATE})?{ws}\}}"#, ws = "SPACE"),
1296                vec![r#"{SPACE"date"SPACE:SPACE"2018-11-13"SPACE}"#],
1297            ),
1298        ] {
1299            let regex = regex_from_str(schema, whitespace_pattern).expect("To regex failed");
1300            assert_eq!(regex, expected_regex);
1301
1302            let re = Regex::new(&regex).expect("Regex failed");
1303            for m in a_match {
1304                should_match(&re, m);
1305            }
1306        }
1307    }
1308
1309    #[test]
1310    fn direct_recursion_in_array_and_default_behaviour() {
1311        let schema = r##"
1312        {
1313            "type": "object",
1314            "properties": {
1315                "name": { "type": "string" },
1316                "children": {
1317                    "type": "array",
1318                    "items": { "$ref": "#" }
1319                }
1320            }
1321        }"##;
1322
1323        let regex = regex_from_str(schema, None);
1324        assert!(regex.is_ok(), "{:?}", regex);
1325
1326        // Confirm the depth of 3 recursion levels by default, recursion level starts
1327        // when children start to have children
1328        let re = Regex::new(&regex.unwrap()).expect("Regex failed");
1329        for lvl in [
1330            // level 0
1331            r#"{ "name": "Az"}"#,
1332            r#"{ "name": "Az", "children": [] }"#,
1333            r#"{ "name": "Az", "children": [{"name": "Bo"}] }"#,
1334            // level 1
1335            r#"{ "name": "Az", "children": [{"name": "Bo", "children": [] }] }"#,
1336            r#"{ "name": "Az", "children": [{"name": "Bo", "children": [{"name": "Li"}] }] }"#,
1337            // level 2
1338            r#"{ "name": "Az", "children": [{"name": "Bo", "children": [{"name": "Li", "children": [] }] }] }"#,
1339            r#"{ "name": "Az", "children": [{"name": "Bo", "children": [{"name": "Li", "children": [{"name": "Ho"}] }] }] }"#,
1340            // level 3
1341            r#"{ "name": "Az", "children": [{"name": "Bo", "children": [{"name": "Li", "children": [{"name": "Ho", "children": [] }] }] }] }"#,
1342            r#"{ "name": "Az", "children": [{"name": "Bo", "children": [{"name": "Li", "children": [{"name": "Ho", "children": [{"name": "Ro"}] }] }] }] }"#,
1343        ] {
1344            should_match(&re, lvl);
1345        }
1346
1347        for lvl in [
1348            // level 4
1349            r#"{ "name": "Az", "children": [{"name": "Bo", "children": [{"name": "Li", "children": [{"name": "Ho", "children": [{"name": "Ro", "children": [] }] }] }] }] }"#,
1350            r#"{ "name": "Az", "children": [{"name": "Bo", "children": [{"name": "Li", "children": [{"name": "Ho", "children": [{"name": "Ro", "children": [{"name": "Ks"}] }] }] }] }] }"#,
1351        ] {
1352            should_not_match(&re, lvl);
1353        }
1354    }
1355
1356    #[test]
1357    fn indirect_recursion_with_recursion_level_regex_match() {
1358        let json = r##"{
1359          "type": "object",
1360          "properties": {
1361              "node": { "$ref": "#/definitions/node" }
1362          },
1363          "definitions": {
1364              "node": {
1365                  "type": "object",
1366                  "properties": {
1367                      "value": { "type": "integer" },
1368                      "next": { "$ref": "#/definitions/node" }
1369                  }
1370              }
1371          }
1372        }"##;
1373        let json_value: Value = serde_json::from_str(json).expect("Can't parse json");
1374        let mut parser = parsing::Parser::new(&json_value).with_max_recursion_depth(0);
1375
1376        let result = parser.to_regex(&json_value);
1377        assert!(result.is_ok(), "{:?}", result);
1378        let regex = result.unwrap();
1379        assert_eq!(
1380            r#"\{([ ]?"node"[ ]?:[ ]?\{([ ]?"value"[ ]?:[ ]?(-)?(0|[1-9][0-9]*))?[ ]?\})?[ ]?\}"#,
1381            regex,
1382        );
1383
1384        //  More readable version to confirm that logic is correct.
1385        //  Recursion depth 1:
1386        //  {
1387        //      ("node":
1388        //          {
1389        //              ("value":(-)?(0|[1-9][0-9]*)(,"next":{("value":(-)?(0|[1-9][0-9]*))?})?
1390        //              |
1391        //              ("value":(-)?(0|[1-9][0-9]*),)?"next":{("value":(-)?(0|[1-9][0-9]*))?})?
1392        //          }
1393        //      )?
1394        //  }
1395        //  Recursion depth 2:
1396        //  {
1397        //      ("node":
1398        //          {
1399        //              ("value":(-)?(0|[1-9][0-9]*)(,"next":{
1400        //                  ("value":(-)?(0|[1-9][0-9]*)(,"next":{("value":(-)?(0|[1-9][0-9]*))?})?
1401        //                  |
1402        //                  ("value":(-)?(0|[1-9][0-9]*),)?"next":{("value":(-)?(0|[1-9][0-9]*))?})?
1403        //              })?
1404        //              |
1405        //              ("value":(-)?(0|[1-9][0-9]*),)?"next":{
1406        //                  ("value":(-)?(0|[1-9][0-9]*)(,"next":{("value":(-)?(0|[1-9][0-9]*))?})?
1407        //                  |
1408        //                  ("value":(-)?(0|[1-9][0-9]*),)?"next":{("value":(-)?(0|[1-9][0-9]*))?})?
1409        //              })?
1410        //          }
1411        //      )?
1412        // }
1413        let mut parser = parser.with_max_recursion_depth(1);
1414        let result = parser.to_regex(&json_value);
1415        assert!(result.is_ok(), "{:?}", result);
1416        let regex = result.unwrap();
1417        assert_eq!(
1418            r#"\{([ ]?"node"[ ]?:[ ]?\{([ ]?"value"[ ]?:[ ]?(-)?(0|[1-9][0-9]*)|([ ]?"value"[ ]?:[ ]?(-)?(0|[1-9][0-9]*)[ ]?,)?[ ]?"next"[ ]?:[ ]?\{([ ]?"value"[ ]?:[ ]?(-)?(0|[1-9][0-9]*))?[ ]?\})?[ ]?\})?[ ]?\}"#,
1419            regex,
1420        );
1421    }
1422
1423    #[test]
1424    fn triple_recursion_doesnt_fail() {
1425        let schema = r##"
1426        {
1427            "definitions": {
1428                "typeA": {
1429                    "type": "object",
1430                    "properties": {
1431                        "name": { "type": "string" },
1432                        "child": { "$ref": "#/definitions/typeB" }
1433                    },
1434                    "required": ["name"]
1435                },
1436                "typeB": {
1437                    "type": "object",
1438                    "properties": {
1439                        "value": { "type": "number" },
1440                        "next": { "$ref": "#/definitions/typeC" }
1441                    },
1442                    "required": ["value"]
1443                },
1444                "typeC": {
1445                    "type": "object",
1446                    "properties": {
1447                        "flag": { "type": "boolean" },
1448                        "parent": { "$ref": "#/definitions/typeA" }
1449                    },
1450                    "required": ["flag"]
1451                }
1452           },
1453          "$ref": "#/definitions/typeA"
1454        }"##;
1455
1456        let regex = regex_from_str(schema, None);
1457        assert!(regex.is_ok(), "{:?}", regex);
1458    }
1459}