# json.schema

> A module of json_mlake's API.

## Structs

### `ValidationError`

```mojo
struct ValidationError
```

One reason an instance failed, and where both ends of it are.

`path` is a JSON Pointer into the instance and `keyword_location`
is a JSON Pointer into the schema. Reporting only the first leaves
the caller guessing which of the keywords covering that location
objected, which is the common case as soon as a schema uses
`allOf` or `$ref`.

Implements: `Copyable`, `Movable`, `Writable`

Fields:

- `path: String`
- `keyword_location: String`
- `message: String`

#### `__init__`

```mojo
def __init__(out self, path: String, message: String)
```

```mojo
def __init__(out self, path: String, keyword_location: String, message: String)
```

#### `__str__`

```mojo
def __str__(self) -> String
```

#### `write_to`

```mojo
def write_to[W: Writer](self, mut writer: W)
```

### `FormatAnnotation`

```mojo
struct FormatAnnotation
```

One `format` keyword that was reached, and what it observed.

Draft 2020-12 section 7.2.1 makes `format` an annotation by
default. Collecting the observation rather than discarding it is
what makes the default mode useful: a caller can report a bad
email address without having turned every `format` in the schema
into an assertion.

Implements: `Copyable`, `Movable`

Fields:

- `path: String`
- `format: String`
- `matched: Bool`

### `ValidationResult`

```mojo
struct ValidationResult
```

The verdict, every reason for it, and the `format` annotations.

Implements: `Boolable`, `Movable`

Fields:

- `valid: Bool`
- `errors: List[ValidationError]`
- `format_annotations: List[FormatAnnotation]`

#### `__init__`

```mojo
def __init__(out self)
```

#### `__bool__`

```mojo
def __bool__(self) -> Bool
```

#### `add_error`

```mojo
def add_error(mut self, path: String, message: String)
```

```mojo
def add_error(mut self, path: String, keyword_location: String, message: String)
```

### `Schema`

```mojo
struct Schema
```

A schema document compiled once, ready to validate many times.

`validate(document, schema)` compiles on every call, which is the
right shape for a one-off check and the wrong one for a loop over a
file of records: the schema is walked, its patterns are compiled
and its references are resolved once per document rather than once.
Compiling separately also moves every malformed-schema error to the
point where the schema is handed over, so a bad schema is not
reported as a bad document.

Implements: `Movable`

#### `__init__`

```mojo
def __init__(out self, var nodes: List[_Node], var regexes: List[Regex], root: Int, assert_format: Bool)
```

#### `compile`

```mojo
def compile(schema: Value) -> Self
```

Compile a schema document.

Args:

- `schema`: The schema, as a parsed JSON value. A boolean is a
    schema too: `true` accepts every instance and `false`
    rejects every instance.

Raises: Error: If the document is not a valid schema. A keyword
with an operand of the wrong type, a `pattern` outside
I-Regexp and a `$ref` that names nothing in the
document are all reported here rather than turning
into a silent pass at validation time.

```mojo
def compile(schema: Value, assert_format: Bool) -> Self
```

Compile a schema document, choosing how `format` behaves.

Args:

- `schema`: The schema, as a parsed JSON value.
- `assert_format`: True to make `format` an assertion, so a
    string that does not satisfy its format attribute
    fails. The default is the specification's own default,
    where `format` is collected as an annotation and never
    changes the verdict.

Raises: Error: If the document is not a valid schema.

#### `validate`

```mojo
def validate(self, document: Value) -> ValidationResult
```

Validate one document, collecting every reason it failed.

Args:

- `document`: The instance to check.

Raises: Error: If a `$ref` cycle with no base case runs the
evaluation past its depth budget.

#### `is_valid`

```mojo
def is_valid(self, document: Value) -> Bool
```

Whether `document` satisfies the schema.

Args:

- `document`: The instance to check.

Raises: Error: If a `$ref` cycle with no base case runs the
evaluation past its depth budget.

## Functions

### `validate`

```mojo
def validate(document: Value, schema: Value) -> ValidationResult
```

Validate a JSON document against a JSON Schema (draft 2020-12).

Every keyword of the core, applicator, validation and
unevaluated-location vocabularies is implemented, along with
`format` as an annotation. `$ref` resolves inside the schema
document, through a JSON Pointer fragment or an `$anchor`.

To check many documents against one schema, compile it once with
`Schema.compile` instead: this entry point recompiles on every
call.

Example:
var schema = loads('{"type":"object","required":["name"]}')
var doc = loads('{"name":"Alice"}')
var result = validate(doc, schema)
if result:
    print("Valid!").

Args:

- `document`: The JSON document to validate.
- `schema`: The JSON Schema.

Raises: Error: If the schema is not a valid schema document, or if a
`$ref` cycle with no base case runs the evaluation past its
depth budget.

### `is_valid`

```mojo
def is_valid(document: Value, schema: Value) -> Bool
```

Check whether a document is valid against a schema.

Args:

- `document`: The JSON document to validate.
- `schema`: The JSON Schema.

Raises: Error: If the schema is not a valid schema document, or if a
`$ref` cycle with no base case runs the evaluation past its
depth budget.
