From 8df5edcd18220b72180fd24294e4936aaee8f5f8 Mon Sep 17 00:00:00 2001 From: Daniel Parker Date: Fri, 22 Dec 2023 12:17:54 -0500 Subject: [PATCH] jsonschema draft2019-09 $anchor --- .../draft201909/schema_parser_impl.hpp | 81 ++++++++----------- .../jsonschema/draft7/schema_parser_impl.hpp | 77 +++++++++--------- .../src/jsonschema_draft201909_tests.cpp | 2 +- .../src/jsonschema_draft7_tests.cpp | 2 +- 4 files changed, 73 insertions(+), 89 deletions(-) diff --git a/include/jsoncons_ext/jsonschema/draft201909/schema_parser_impl.hpp b/include/jsoncons_ext/jsonschema/draft201909/schema_parser_impl.hpp index b807f6b776..75ef6cae00 100644 --- a/include/jsoncons_ext/jsonschema/draft201909/schema_parser_impl.hpp +++ b/include/jsoncons_ext/jsonschema/draft201909/schema_parser_impl.hpp @@ -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()) @@ -106,15 +104,19 @@ namespace draft201909 { if (schema.template as()) { 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: { @@ -122,12 +124,11 @@ namespace draft201909 { if (it != schema.object_range().end()) // this schema is a reference { schema_location relative(it->value().template as()); - + 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()) @@ -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(); + 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(); - 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(sch); + return jsoncons::make_unique(validator); } void init_type_mapping(std::vector& type_mapping, const std::string& type, @@ -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") @@ -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 diff --git a/include/jsoncons_ext/jsonschema/draft7/schema_parser_impl.hpp b/include/jsoncons_ext/jsonschema/draft7/schema_parser_impl.hpp index 327f894e83..9c10fa08bb 100644 --- a/include/jsoncons_ext/jsonschema/draft7/schema_parser_impl.hpp +++ b/include/jsoncons_ext/jsonschema/draft7/schema_parser_impl.hpp @@ -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()) @@ -104,65 +104,60 @@ namespace draft7 { if (schema.template as()) { 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()); - 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(sch); + return jsoncons::make_unique(validator); } void init_type_mapping(std::vector& type_mapping, const std::string& type, @@ -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) @@ -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 diff --git a/test/jsonschema/src/jsonschema_draft201909_tests.cpp b/test/jsonschema/src/jsonschema_draft201909_tests.cpp index 00f8524f1f..324c8eac82 100644 --- a/test/jsonschema/src/jsonschema_draft201909_tests.cpp +++ b/test/jsonschema/src/jsonschema_draft201909_tests.cpp @@ -83,7 +83,7 @@ namespace { } } -TEST_CASE("jsonschema-tests") +TEST_CASE("jsonschema draft2019-09 tests") { SECTION("issues") { diff --git a/test/jsonschema/src/jsonschema_draft7_tests.cpp b/test/jsonschema/src/jsonschema_draft7_tests.cpp index f5db4e8001..d7c81a7742 100644 --- a/test/jsonschema/src/jsonschema_draft7_tests.cpp +++ b/test/jsonschema/src/jsonschema_draft7_tests.cpp @@ -83,7 +83,7 @@ namespace { } } -TEST_CASE("jsonschema-tests") +TEST_CASE("jsonschema draft7 tests") { SECTION("issues") {