Skip to content

Commit

Permalink
jsonschema draft2019-09 $anchor
Browse files Browse the repository at this point in the history
  • Loading branch information
danielaparker committed Dec 22, 2023
1 parent 28bb481 commit 8df5edc
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 89 deletions.
81 changes: 35 additions & 46 deletions include/jsoncons_ext/jsonschema/draft201909/schema_parser_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,7 @@ namespace draft201909 {
{
auto new_context = context.update_uris(schema, keys);

std::cout << "make_subschema_validator:\n" << pretty_print(schema) << "\n\n";

validator_pointer sch = nullptr;
validator_pointer validator = nullptr;

bool is_ref = false;
switch (schema.type())
Expand All @@ -106,28 +104,31 @@ namespace draft201909 {
if (schema.template as<bool>())
{
auto ref = make_true_validator(new_context);
sch = ref.get();
validator = ref.get();
subschemas_.emplace_back(std::move(ref));
}
else
{
auto ref = make_false_validator(new_context);
sch = ref.get();
validator = ref.get();
subschemas_.emplace_back(std::move(ref));
}
for (const auto& uri : new_context.uris())
{
insert_schema(uri, validator);
}
break;
case json_type::object_value:
{
auto it = schema.find("$ref");
if (it != schema.object_range().end()) // this schema is a reference
{
schema_location relative(it->value().template as<std::string>());

is_ref = true;
auto id = context.resolve_back(relative);
auto ref = get_or_create_reference(id);
sch = ref.get();
validator = ref.get();
subschemas_.emplace_back(std::move(ref));
is_ref = true;
}
it = schema.find("$defs");
if (it != schema.object_range().end())
Expand All @@ -148,44 +149,32 @@ namespace draft201909 {
if (!is_ref)
{
auto ref = make_type_validator(schema, new_context);
sch = ref.get();
validator = ref.get();
subschemas_.emplace_back(std::move(ref));
it = schema.find("$anchor"); // If $anchor is found, this schema can be referenced by the id
if (it != schema.object_range().end())
{
std::string id = it->value().template as<std::string>();
schema_location relative("#"+id);
insert_schema(relative, validator);
}
}
for (const auto& uri : new_context.uris())
{
insert_schema(uri, validator);
for (const auto& item : schema.object_range())
{
insert_unknown_keyword(uri, item.key(), item.value()); // save unknown keywords for later reference
}
}
break;
}
default:
JSONCONS_THROW(schema_error("invalid JSON-type for a schema for " + new_context.get_absolute_uri().string() + ", expected: boolean or object"));
break;
}

if (!is_ref)
{
if (schema.is_object())
{
auto it = schema.find("$anchor"); // If $anchor is found, this schema can be referenced by the id
if (it != schema.object_range().end())
{
std::string id = it->value().template as<std::string>();
schema_location relative("#"+id);
insert_schema(relative, sch);
}
}
for (const auto& uri : new_context.uris())
{
if (schema.is_object())
{
insert_schema(uri, sch);
for (const auto& item : schema.object_range())
insert_unknown_keyword(uri, item.key(), item.value()); // save unknown keywords for later reference
}
else
{
insert_schema(uri, sch);
}
}
}

return jsoncons::make_unique<reference_validator_type>(sch);
return jsoncons::make_unique<reference_validator_type>(validator);
}

void init_type_mapping(std::vector<validator_type>& type_mapping, const std::string& type,
Expand Down Expand Up @@ -1069,17 +1058,17 @@ namespace draft201909 {
);
}

void parse(const Json& sch) override
void parse(const Json& schema) override
{
parse(sch, "#");
parse(schema, "#");
}

void parse(const Json& sch, const std::string& retrieval_uri) override
void parse(const Json& schema, const std::string& retrieval_uri) override
{
if (sch.is_object())
if (schema.is_object())
{
auto it = sch.find("$schema");
if (it != sch.object_range().end())
auto it = schema.find("$schema");
if (it != schema.object_range().end())
{
auto sv = it->value().as_string_view();
if (sv != "https://json-schema.org/draft/2019-09/schema")
Expand All @@ -1090,13 +1079,13 @@ namespace draft201909 {
}
}
}
load(sch, compilation_context(schema_location(retrieval_uri)));
load(schema, compilation_context(schema_location(retrieval_uri)));
}

void load(const Json& sch, const compilation_context& context)
void load(const Json& schema, const compilation_context& context)
{
subschema_registries_.clear();
root_ = make_subschema_validator(sch, context, {});
root_ = make_subschema_validator(schema, context, {});

// load all external schemas that have not already been loaded

Expand Down
77 changes: 36 additions & 41 deletions include/jsoncons_ext/jsonschema/draft7/schema_parser_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ namespace draft7 {
{
auto new_context = context.update_uris(schema, keys);

validator_pointer sch = nullptr;
validator_pointer validator = nullptr;

bool is_ref = false;
switch (schema.type())
Expand All @@ -104,65 +104,60 @@ namespace draft7 {
if (schema.template as<bool>())
{
auto ref = make_true_validator(new_context);
sch = ref.get();
validator = ref.get();
subschemas_.emplace_back(std::move(ref));
}
else
{
auto ref = make_false_validator(new_context);
sch = ref.get();
validator = ref.get();
subschemas_.emplace_back(std::move(ref));
}
for (const auto& uri : new_context.uris())
{
insert_schema(uri, validator);
}
break;
case json_type::object_value:
{
auto it = schema.find("$ref");
if (it != schema.object_range().end()) // this schema is a reference
{
is_ref = true;
schema_location relative(it->value().template as<std::string>());

auto id = context.resolve_back(relative);
auto ref = get_or_create_reference(id);
sch = ref.get();
validator = ref.get();
subschemas_.emplace_back(std::move(ref));
}
else
}
it = schema.find("definitions");
if (it != schema.object_range().end())
{
for (const auto& def : it->value().object_range())
make_subschema_validator(def.value(), new_context, {"definitions", def.key()});
}
if (!is_ref)
{
it = schema.find("definitions");
if (it != schema.object_range().end())
{
for (const auto& def : it->value().object_range())
make_subschema_validator(def.value(), new_context, {"definitions", def.key()});
}
auto ref = make_type_validator(schema, new_context);
sch = ref.get();
validator = ref.get();
subschemas_.emplace_back(std::move(ref));
}
for (const auto& uri : new_context.uris())
{
insert_schema(uri, validator);
for (const auto& item : schema.object_range())
{
insert_unknown_keyword(uri, item.key(), item.value()); // save unknown keywords for later reference
}
}
break;
}
default:
JSONCONS_THROW(schema_error("invalid JSON-type for a schema for " + new_context.get_absolute_uri().string() + ", expected: boolean or object"));
break;
}

if (!is_ref)
{
for (const auto& uri : new_context.uris())
{
if (schema.is_object())
{
insert_schema(uri, sch);
for (const auto& item : schema.object_range())
insert_unknown_keyword(uri, item.key(), item.value()); // save unknown keywords for later reference
}
else
{
insert_schema(uri, sch);
}
}
}

return jsoncons::make_unique<reference_validator_type>(sch);
return jsoncons::make_unique<reference_validator_type>(validator);
}

void init_type_mapping(std::vector<validator_type>& type_mapping, const std::string& type,
Expand Down Expand Up @@ -1046,17 +1041,17 @@ namespace draft7 {
);
}

void parse(const Json& sch) override
void parse(const Json& schema) override
{
parse(sch, "#");
parse(schema, "#");
}

void parse(const Json& sch, const std::string& retrieval_uri) override
void parse(const Json& schema, const std::string& retrieval_uri) override
{
if (sch.is_object())
if (schema.is_object())
{
auto it = sch.find("$schema");
if (it != sch.object_range().end())
auto it = schema.find("$schema");
if (it != schema.object_range().end())
{
auto sv = it->value().as_string_view();
if (sv.find("json-schema.org/draft-07/schema#") == string_view::npos)
Expand All @@ -1067,13 +1062,13 @@ namespace draft7 {
}
}
}
load(sch, compilation_context(schema_location(retrieval_uri)));
load(schema, compilation_context(schema_location(retrieval_uri)));
}

void load(const Json& sch, const compilation_context& context)
void load(const Json& schema, const compilation_context& context)
{
subschema_registries_.clear();
root_ = make_subschema_validator(sch, context, {});
root_ = make_subschema_validator(schema, context, {});

// load all external schemas that have not already been loaded

Expand Down
2 changes: 1 addition & 1 deletion test/jsonschema/src/jsonschema_draft201909_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ namespace {
}
}

TEST_CASE("jsonschema-tests")
TEST_CASE("jsonschema draft2019-09 tests")
{
SECTION("issues")
{
Expand Down
2 changes: 1 addition & 1 deletion test/jsonschema/src/jsonschema_draft7_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ namespace {
}
}

TEST_CASE("jsonschema-tests")
TEST_CASE("jsonschema draft7 tests")
{
SECTION("issues")
{
Expand Down

0 comments on commit 8df5edc

Please sign in to comment.