Skip to content

Commit

Permalink
Implement the hierarchical output format
Browse files Browse the repository at this point in the history
  • Loading branch information
marksparkza committed Nov 12, 2022
1 parent bce6b70 commit 5740bd2
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 2 deletions.
41 changes: 40 additions & 1 deletion jschon/output.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Any, Callable, Dict, Iterable

from jschon.json import JSONCompatible
from jschon.jsonschema import Result
from jschon.jsonschema import JSONSchema, Result

__all__ = [
'OutputFormatter',
Expand Down Expand Up @@ -124,3 +124,42 @@ def visit(node: Result):
return output

return visit(result)


@output_formatter('hierarchical')
def hierarchical(result: Result) -> JSONCompatible:
def visit(node: Result):
if isinstance(node.schema_node, JSONSchema):
output = {
"valid": (valid := node.valid),
"evaluationPath": str(node.path),
"schemaLocation": str(node.absolute_uri),
"instanceLocation": str(node.instance.path),
}
nested = []
annotations = {}
errors = {}
for child in node.children.values():
nested += [
childout for childout in (visit(child))
if child.valid == valid
]
if valid and child.annotation is not None:
annotations[child.key] = child.annotation
elif not valid and child.error is not None:
errors[child.key] = child.error

if nested:
output["nested"] = nested
if valid and annotations:
output["annotations"] = annotations
elif not valid and errors:
output["errors"] = errors

yield output

else:
for child in node.children.values():
yield from visit(child)

return list(visit(result))[0]
25 changes: 24 additions & 1 deletion tests/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pytest
from pytest import param as p

from jschon import JSON, JSONPointer, JSONSchema
from jschon import JSON, JSONPointer, JSONSchema, URI
from tests import metaschema_uri_2019_09, metaschema_uri_2020_12

schema_valid = {
Expand Down Expand Up @@ -413,3 +413,26 @@ def test_basic_output_filtering(annotations):
if JSONPointer(annotation['keywordLocation'])[-1] in annotations
]
assert result == filtered_output


@pytest.mark.parametrize('input, valid', [
([1, 2], True),
(['one'], True),
([1, 'two'], False),
([None, False], False),
])
def test_hierarchical_output(input, valid, catalog):
schema = JSONSchema({
"$schema": "https://json-schema.org/draft/next/schema",
"type": "array",
"anyOf": [
{"items": {"type": "integer"}},
{"items": {"type": "string"}},
]
})
output = schema.evaluate(JSON(input)).output('hierarchical')
assert output['valid'] is valid

output_schema = catalog.get_schema(URI('https://json-schema.org/draft/next/output/schema'))
output_validity = output_schema.evaluate(JSON(output))
assert output_validity.valid is True

0 comments on commit 5740bd2

Please sign in to comment.