move checks contentEncoding and contentMediaType to string schema
This commit is contained in:
parent
a632d2707b
commit
dbf59ab4c3
@ -470,25 +470,8 @@ class type_schema : public schema
|
||||
else_->validate(ptr, instance, patch, e);
|
||||
}
|
||||
}
|
||||
|
||||
// special treatment
|
||||
if ((instance.type() == json::value_t::string || instance.type() == json::value_t::binary) &&
|
||||
std::get<0>(content_)) {
|
||||
if (root_->content_check() == nullptr)
|
||||
e.error(ptr, instance, std::string("a content checker was not provided but a contentEncoding or contentMediaType for this string have been present: '") + std::get<1>(content_) + "' '" + std::get<2>(content_) + "'");
|
||||
else {
|
||||
try {
|
||||
root_->content_check()(std::get<1>(content_), std::get<2>(content_), instance);
|
||||
} catch (const std::exception &ex) {
|
||||
e.error(ptr, instance, std::string("content-checking failed: ") + ex.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
std::tuple<bool, std::string, std::string> content_{false, "", ""};
|
||||
|
||||
public:
|
||||
type_schema(json &sch,
|
||||
root_schema *root,
|
||||
@ -553,6 +536,11 @@ public:
|
||||
// we stick with JSON-schema: use the integer-validator if instance-value is unsigned
|
||||
type_[(uint8_t) json::value_t::number_unsigned] = type_[(uint8_t) json::value_t::number_integer];
|
||||
|
||||
// special for binary types
|
||||
if (type_[(uint8_t) json::value_t::string]) {
|
||||
type_[(uint8_t) json::value_t::binary] = type_[(uint8_t) json::value_t::string];
|
||||
}
|
||||
|
||||
attr = sch.find("enum");
|
||||
if (attr != sch.end()) {
|
||||
enum_ = {true, attr.value()};
|
||||
@ -609,41 +597,6 @@ public:
|
||||
}
|
||||
sch.erase(attr);
|
||||
}
|
||||
|
||||
attr = sch.find("contentEncoding");
|
||||
if (attr != sch.end()) {
|
||||
std::get<0>(content_) = true;
|
||||
std::get<1>(content_) = attr.value().get<std::string>();
|
||||
|
||||
// special case for nlohmann::json-binary-types
|
||||
//
|
||||
// https://github.com/pboettch/json-schema-validator/pull/114
|
||||
//
|
||||
// We cannot use explicitly in a schema: {"type": "binary"} or
|
||||
// "type": ["binary", "number"] we have to be implicit. For a
|
||||
// schema where "contentEncoding" is set to "binary", an instance
|
||||
// of type json::value_t::binary is accepted. If a
|
||||
// contentEncoding-callback has to be provided and is called
|
||||
// accordingly. For encoding=binary, no other type validations are done
|
||||
|
||||
if (attr.value() == "binary") {
|
||||
// clear out all other type-schemas
|
||||
for (auto &type_valid : type_)
|
||||
type_valid = nullptr;
|
||||
|
||||
// when no schema-type is explicitly given, we accept binary-values
|
||||
type_[(uint8_t) json::value_t::binary] = type_schema::make(sch, json::value_t::binary, root, uris, known_keywords);
|
||||
}
|
||||
|
||||
sch.erase(attr);
|
||||
}
|
||||
|
||||
attr = sch.find("contentMediaType");
|
||||
if (attr != sch.end()) {
|
||||
std::get<0>(content_) = true;
|
||||
std::get<2>(content_) = attr.value().get<std::string>();
|
||||
sch.erase(attr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -658,11 +611,12 @@ class string : public schema
|
||||
#endif
|
||||
|
||||
std::pair<bool, std::string> format_;
|
||||
std::tuple<bool, std::string, std::string> content_{false, "", ""};
|
||||
|
||||
std::size_t utf8_length(const std::string &s) const
|
||||
{
|
||||
size_t len = 0;
|
||||
for (const unsigned char &c : s)
|
||||
for (unsigned char c : s)
|
||||
if ((c & 0xc0) != 0x80)
|
||||
len++;
|
||||
return len;
|
||||
@ -686,6 +640,24 @@ class string : public schema
|
||||
}
|
||||
}
|
||||
|
||||
if (std::get<0>(content_)) {
|
||||
if (root_->content_check() == nullptr)
|
||||
e.error(ptr, instance, std::string("a content checker was not provided but a contentEncoding or contentMediaType for this string have been present: '") + std::get<1>(content_) + "' '" + std::get<2>(content_) + "'");
|
||||
else {
|
||||
try {
|
||||
root_->content_check()(std::get<1>(content_), std::get<2>(content_), instance);
|
||||
} catch (const std::exception &ex) {
|
||||
e.error(ptr, instance, std::string("content-checking failed: ") + ex.what());
|
||||
}
|
||||
}
|
||||
} else if (instance.type() == json::value_t::binary) {
|
||||
e.error(ptr, instance, "expected string, but get binary data");
|
||||
}
|
||||
|
||||
if (instance.type() != json::value_t::string) {
|
||||
return; // next checks only for strings
|
||||
}
|
||||
|
||||
#ifndef NO_STD_REGEX
|
||||
if (pattern_.first &&
|
||||
!REGEX_NAMESPACE::regex_search(instance.get<std::string>(), pattern_.second))
|
||||
@ -721,6 +693,33 @@ public:
|
||||
sch.erase(attr);
|
||||
}
|
||||
|
||||
attr = sch.find("contentEncoding");
|
||||
if (attr != sch.end()) {
|
||||
std::get<0>(content_) = true;
|
||||
std::get<1>(content_) = attr.value().get<std::string>();
|
||||
|
||||
// special case for nlohmann::json-binary-types
|
||||
//
|
||||
// https://github.com/pboettch/json-schema-validator/pull/114
|
||||
//
|
||||
// We cannot use explicitly in a schema: {"type": "binary"} or
|
||||
// "type": ["binary", "number"] we have to be implicit. For a
|
||||
// schema where "contentEncoding" is set to "binary", an instance
|
||||
// of type json::value_t::binary is accepted. If a
|
||||
// contentEncoding-callback has to be provided and is called
|
||||
// accordingly. For encoding=binary, no other type validations are done
|
||||
|
||||
sch.erase(attr);
|
||||
}
|
||||
|
||||
attr = sch.find("contentMediaType");
|
||||
if (attr != sch.end()) {
|
||||
std::get<0>(content_) = true;
|
||||
std::get<2>(content_) = attr.value().get<std::string>();
|
||||
|
||||
sch.erase(attr);
|
||||
}
|
||||
|
||||
#ifndef NO_STD_REGEX
|
||||
attr = sch.find("pattern");
|
||||
if (attr != sch.end()) {
|
||||
@ -1180,13 +1179,8 @@ std::shared_ptr<schema> type_schema::make(json &schema,
|
||||
case json::value_t::discarded: // not a real type - silence please
|
||||
break;
|
||||
|
||||
case json::value_t::binary: {
|
||||
// can be used for validate bson or other binary representation of json
|
||||
// - specific to nlohmann::json - this type is not standardized
|
||||
// json-schema-draft-7
|
||||
json tmp = true;
|
||||
return std::make_shared<boolean>(tmp, root); // always true - content-check with do the work
|
||||
}
|
||||
case json::value_t::binary:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -80,18 +80,17 @@ public:
|
||||
|
||||
static void content(const std::string &contentEncoding, const std::string &contentMediaType, const json &instance)
|
||||
{
|
||||
if (instance.type() != json::value_t::binary)
|
||||
throw std::invalid_argument("invalid instance type for binary content checker");
|
||||
|
||||
std::cerr << "mediaType: '" << contentMediaType << "', encoding: '" << contentEncoding << "'\n";
|
||||
|
||||
if (contentMediaType != "")
|
||||
throw std::invalid_argument("unable to check for contentMediaType " + contentMediaType);
|
||||
|
||||
if (contentEncoding == "binary") {
|
||||
|
||||
} else if (contentEncoding != "")
|
||||
throw std::invalid_argument("unable to check for contentEncoding " + contentEncoding);
|
||||
if (instance.type() != json::value_t::binary) {
|
||||
throw std::invalid_argument{"expected binary data"};
|
||||
}
|
||||
} else {
|
||||
if (instance.type() == json::value_t::binary) {
|
||||
throw std::invalid_argument{"expected string, but get binary"};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
@ -117,9 +116,8 @@ int main()
|
||||
|
||||
// invalid binary data
|
||||
val.validate({{"binary_data", "string, but expect binary data"}}, err);
|
||||
EXPECT_EQ(err.failed_pointers.size(), 2);
|
||||
EXPECT_EQ(err.failed_pointers.size(), 1);
|
||||
EXPECT_EQ(err.failed_pointers[0].to_string(), "/binary_data");
|
||||
EXPECT_EQ(err.failed_pointers[1].to_string(), "/binary_data"); // second error comes from content-checker
|
||||
err.reset();
|
||||
|
||||
// also check that simple string not accept binary data
|
||||
@ -133,10 +131,13 @@ int main()
|
||||
|
||||
// check simple types
|
||||
val.set_root_schema(array_of_types);
|
||||
val.validate({{"something", "string"}}, err);
|
||||
val.validate({{"something", 1}}, err);
|
||||
val.validate({{"something", false}}, err);
|
||||
EXPECT_EQ(err.failed_pointers.size(), 4); // binary encoding invalidated all other types
|
||||
// TODO when we set `string` in array and set `contentEncoding` = "binary" - what it means? We expected string or binary?
|
||||
// Or we expect only binary? Now if you set `contentEncoding` = "binary", then it means that you expect only binary data,
|
||||
// not string
|
||||
//val.validate({{"something", "string"}}, err); -> produce error about type
|
||||
EXPECT_EQ(err.failed_pointers.size(), 0);
|
||||
err.reset();
|
||||
|
||||
// check binary data
|
||||
@ -165,9 +166,8 @@ int main()
|
||||
|
||||
// invalid binary data
|
||||
val_no_content.validate({{"binary_data", "string, but expect binary data"}}, err);
|
||||
EXPECT_EQ(err.failed_pointers.size(), 2);
|
||||
EXPECT_EQ(err.failed_pointers.size(), 1);
|
||||
EXPECT_EQ(err.failed_pointers[0].to_string(), "/binary_data");
|
||||
EXPECT_EQ(err.failed_pointers[1].to_string(), "/binary_data"); // second error comes from content-checker
|
||||
err.reset();
|
||||
|
||||
// also check that simple string not accept binary data
|
||||
@ -177,6 +177,5 @@ int main()
|
||||
EXPECT_EQ(err.failed_pointers[1].to_string(), "/standard_string");
|
||||
err.reset();
|
||||
|
||||
|
||||
return error_count;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user