Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply patch before to validate "if" #230

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 35 additions & 4 deletions src/json-validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,37 @@ bool logical_combination<oneOf>::is_validate_complete(const json &instance, cons
return count > 1;
}

json apply_patch_from(const json &instance, const json_patch &patch, const json::json_pointer &ptr)
{
if (patch.operator json().empty()) {
return instance;
}

json patched_instance = json::parse(instance.dump());

json array = patch.operator json();
std::string ptr_string = ptr.to_string();
size_t ptr_string_length = ptr_string.length();
for (auto item = array.begin(); item != array.end(); ++item) {
std::string path = item->at("path");
if (path.find(ptr_string) != 0)
continue;
try {
json single_patch = {
{
{"path", path.substr(ptr_string_length)}, //
{"op", item->at("op")}, //
{"value", item->at("value")} //
} //
};
patched_instance = patched_instance.patch(single_patch);
} catch (...) {
}
}

return patched_instance;
}

class type_schema : public schema
{
std::vector<std::shared_ptr<schema>> type_;
Expand Down Expand Up @@ -543,14 +574,14 @@ class type_schema : public schema

if (if_) {
first_error_handler err;

if_->validate(ptr, instance, patch, err);
json patched_instance = apply_patch_from(instance, patch, ptr);
if_->validate(ptr, patched_instance, patch, err);
if (!err) {
if (then_)
then_->validate(ptr, instance, patch, e);
then_->validate(ptr, patched_instance, patch, e);
} else {
if (else_)
else_->validate(ptr, instance, patch, e);
else_->validate(ptr, patched_instance, patch, e);
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,7 @@ add_test(NAME issue-149-entry-selection COMMAND issue-149-entry-selection)
add_executable(issue-189-default-values issue-189-default-values.cpp)
target_link_libraries(issue-189-default-values nlohmann_json_schema_validator)
add_test(NAME issue-189-default-values COMMAND issue-189-default-values)

add_executable(issue-228-if-default-values issue-228-if-default-values.cpp)
target_link_libraries(issue-228-if-default-values nlohmann_json_schema_validator)
add_test(NAME issue-228-if-default-values COMMAND issue-228-if-default-values)
53 changes: 53 additions & 0 deletions test/issue-228-if-default-values.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <iostream>
#include <nlohmann/json-schema.hpp>

using nlohmann::json;
using nlohmann::json_uri;
using nlohmann::json_schema::json_validator;

static const json default_schema = R"(
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"condition": {
"type": "boolean",
"default": false
},
"data": {
"type": "string",
"default": "default"
}
},
"if": {
"properties": { "condition": { "const": true } }
},
"then": {
"required": ["data"]
}
})"_json;

static void loader(const json_uri &uri, json &schema)
{
schema = default_schema;
}

int main(void)
{
json_validator validator(loader);

validator.set_root_schema(default_schema);

json empty_object = json::object();
validator.validate(empty_object);

json enable_condition = R"({"condition": true})"_json;
auto patch = validator.validate(enable_condition);
enable_condition.patch_inplace(patch);
if (enable_condition.at("data") != "default") {
std::cerr << "Unexpected data: " << enable_condition.at("data") << " instead of 'default'" << std::endl;
return 1;
}

return 0;
}