json/schema: add additionaProperties tests
This commit is contained in:
parent
8c222300ca
commit
d48e36ffd5
@ -16,9 +16,12 @@
|
||||
|
||||
#include "combine.hpp"
|
||||
|
||||
#include "properties.hpp"
|
||||
|
||||
#include "../tree.hpp"
|
||||
|
||||
#include "../../iterator.hpp"
|
||||
#include "../../cast.hpp"
|
||||
|
||||
using util::json::schema::constraint::combine;
|
||||
|
||||
@ -38,6 +41,20 @@ combine::combine (::json::tree::node const &def)
|
||||
}
|
||||
|
||||
m_constraints.push_back (instantiate (key, *val));
|
||||
|
||||
if (key == "additionalProperties") {
|
||||
m_additional = util::cast::known<additional_properties> (m_constraints.back ().get ());
|
||||
m_additional->use (m_properties);
|
||||
m_additional->use (m_patterns);
|
||||
} else if (key == "properties") {
|
||||
m_properties = util::cast::known<properties> (m_constraints.back().get ());
|
||||
if (m_additional)
|
||||
m_additional->use (m_properties);
|
||||
} else if (key == "patternProperties") {
|
||||
m_patterns = util::cast::known<pattern_properties> (m_constraints.back ().get ());
|
||||
if (m_additional)
|
||||
m_additional->use (m_patterns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "base.hpp"
|
||||
|
||||
#include "fwd.hpp"
|
||||
#include "../tree.hpp"
|
||||
|
||||
#include <memory>
|
||||
@ -47,6 +49,10 @@ namespace util::json::schema::constraint {
|
||||
std::string m_version;
|
||||
std::unique_ptr<::json::tree::node> m_default;
|
||||
|
||||
properties *m_properties = nullptr;
|
||||
pattern_properties *m_patterns = nullptr;
|
||||
additional_properties *m_additional = nullptr;
|
||||
|
||||
std::vector<std::unique_ptr<base>> m_constraints;
|
||||
};
|
||||
}
|
@ -67,6 +67,14 @@ properties::validate (output_iterator res, ::json::tree::node &target) const noe
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool
|
||||
properties::has (std::string const &key) const noexcept
|
||||
{
|
||||
return m_properties.cend () != m_properties.find (key);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
std::ostream&
|
||||
properties::describe (std::ostream &os) const
|
||||
@ -121,6 +129,20 @@ pattern_properties::validate (output_iterator res,
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool
|
||||
pattern_properties::has (std::string const &key) const noexcept
|
||||
{
|
||||
return std::any_of (
|
||||
m_patterns.begin (),
|
||||
m_patterns.end (),
|
||||
[&key] (auto const &i)
|
||||
{
|
||||
return std::regex_search (key, i.matcher);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
std::ostream&
|
||||
pattern_properties::describe (std::ostream &os) const
|
||||
@ -133,11 +155,38 @@ pattern_properties::describe (std::ostream &os) const
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
additional_properties::additional_properties (
|
||||
::json::tree::node const &def,
|
||||
properties *_properties,
|
||||
pattern_properties *_patterns
|
||||
)
|
||||
: m_fallback (def)
|
||||
, m_properties (_properties)
|
||||
, m_patterns (_patterns)
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
additional_properties::additional_properties (::json::tree::node const &def):
|
||||
m_fallback (def)
|
||||
additional_properties (def, nullptr, nullptr)
|
||||
{ }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
additional_properties::use (properties *ptr)
|
||||
{
|
||||
m_properties = ptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
additional_properties::use (pattern_properties *ptr)
|
||||
{
|
||||
m_patterns = ptr;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
additional_properties::output_iterator
|
||||
additional_properties::validate (output_iterator res,
|
||||
@ -146,8 +195,15 @@ additional_properties::validate (output_iterator res,
|
||||
if (!target.is_object ())
|
||||
return *res++ = { .rule = *this, .target = target };
|
||||
|
||||
for (auto &[key,val]: target.as_object ())
|
||||
for (auto &[key,val]: target.as_object ()) {
|
||||
// don't check properties that are handled elsewhere
|
||||
if (m_patterns && m_patterns->has (key))
|
||||
continue;
|
||||
if (m_properties && m_properties->has (key))
|
||||
continue;
|
||||
|
||||
res = m_fallback.validate (res, *val);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ namespace util::json::schema::constraint {
|
||||
output_iterator validate (output_iterator, ::json::tree::node &target) const noexcept override;
|
||||
std::ostream& describe (std::ostream&) const override;
|
||||
|
||||
bool has (std::string const &key) const noexcept;
|
||||
|
||||
private:
|
||||
std::map<std::string,combine> m_properties;
|
||||
};
|
||||
@ -47,6 +49,8 @@ namespace util::json::schema::constraint {
|
||||
output_iterator validate (output_iterator, ::json::tree::node &target) const noexcept override;
|
||||
std::ostream& describe (std::ostream&) const override;
|
||||
|
||||
bool has (std::string const &key) const noexcept;
|
||||
|
||||
private:
|
||||
struct pattern_t {
|
||||
std::string pattern;
|
||||
@ -65,6 +69,9 @@ namespace util::json::schema::constraint {
|
||||
|
||||
virtual ~additional_properties () = default;
|
||||
|
||||
void use (properties*);
|
||||
void use (pattern_properties*);
|
||||
|
||||
output_iterator validate (output_iterator, ::json::tree::node &target) const noexcept override;
|
||||
std::ostream& describe (std::ostream&) const override;
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
null
|
@ -0,0 +1 @@
|
||||
{ "key": null }
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"key": {}
|
||||
}
|
@ -0,0 +1 @@
|
||||
{}
|
@ -0,0 +1 @@
|
||||
{ "key": "value" }
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"additionalProperties": { "type": "string" }
|
||||
}
|
@ -0,0 +1 @@
|
||||
{ "int": "string" }
|
@ -0,0 +1 @@
|
||||
{ "bool": "string" }
|
@ -0,0 +1 @@
|
||||
{ "int": 0 }
|
@ -0,0 +1 @@
|
||||
{ "bool": true }
|
@ -0,0 +1 @@
|
||||
{ "key": "string" }
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"int": 0,
|
||||
"bool": true,
|
||||
"key": "string"
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"properties": {
|
||||
"int": { "type": "integer" }
|
||||
},
|
||||
"patternProperties": {
|
||||
"^bool": { "type": "boolean" }
|
||||
},
|
||||
"additionalProperties": { "type": "string" }
|
||||
}
|
Loading…
Reference in New Issue
Block a user